Skip to content

BinaryFormatter deprecation issue while using PythonEngine.Shutdown() #2469

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Kaz8939 opened this issue Oct 1, 2024 · 7 comments · May be fixed by #2470
Open

BinaryFormatter deprecation issue while using PythonEngine.Shutdown() #2469

Kaz8939 opened this issue Oct 1, 2024 · 7 comments · May be fixed by #2470
Labels

Comments

@Kaz8939
Copy link

Kaz8939 commented Oct 1, 2024

Environment

  • Pythonnet version: 3.0.4
  • Python version: 3.11
  • Operating System: Windows 10
  • .NET Runtime: .NET8/netstandard 2.0

Details

Hi, I am facing a known issue with PythonEngine.Shutdown() that should have been solved. I saw looking around here that many others have had a problem while using the Shutdown function since it caused an exception due to the deprecation of BinaryFormatter in .NET8.
Here the exception I am getting:

System.NotSupportedException: 'BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information.'

I am aware of the workarounds already provided such as the management of "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization" parameter, if I manually manage this set the issue is not presenting anymore, but it seems to me that is more of a patch than a fix.

Since .NET9 will totally get rid of BinaryFormatter, and since I read in other threads that this issue should have been fixed, I was wondering if I was missing something or if the only way to manage this is by manually managing the serialization parameter.

Here follows the code I am using (in a project that targets netstandard2.0, while it is called by a .NET8 project).

using Python.Runtime;
using System;
using System.IO;

namespace ExecutePython
{
    public class Class1
    {
        string filePath;
        
        public Class1(string FilePath) 
        { 
            filePath = FilePath;
            Initialize();
        }

        public void Initialize()
        {
            string pythonDll = @"C:\Users\MyUser\AppData\Local\Programs\Python\Python311\python311.dll";
            Environment.SetEnvironmentVariable("PYTHONNET_PYDLL", pythonDll);
            PythonEngine.Initialize();
        }
        public void ExecutePython()
        {
            string pyCode = File.ReadAllText(filePath);

            using (Py.GIL())
            {
                try
                {
                    PythonEngine.Exec(pyCode);
                }
                catch (Exception ex)
                {
                    //log error
                }
            }
            
            try
            {
                //AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", true);
                PythonEngine.Shutdown();  
                //AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", false);
            }
            catch (Exception e)
            { }
        }
    }
}

The code that is executing correctly in my python script is a sample code, in my case it just pops up a window to see that the script is executing correctly

@filmor
Copy link
Member

filmor commented Oct 1, 2024

Ah, I see. The issue is that BinaryFormatter's constructor still works, so my feeble attempt to catch an exception there will not work.

@lostmsu Suggestions?

  • Should we just switch to the NoopFormatter by default?
  • Should we default to "non-recoverable" in Shutdown and provide a new method to "shutdown with stashing"?

@filmor filmor added the bug label Oct 1, 2024
@lostmsu
Copy link
Member

lostmsu commented Oct 1, 2024

@filmor can't we detect that we are running on .NET Framework/Mono and use BinaryFormatter, otherwise use noo?

@filmor
Copy link
Member

filmor commented Oct 1, 2024

True, that's probably the quick-fix. On the other hand, since this is such an uncommon scenario, wouldn't it make sense to adjust the defaults to also get "quicker" shutdown unless one explicitly chooses otherwise?

@lostmsu
Copy link
Member

lostmsu commented Oct 1, 2024

I'm OK in the future, but right now it would be a breaking change for anyone who happens to use it with Unity.

@christopher-coy
Copy link

So, to clarify, is this blocking us from moving to .net 9?

@davidbitterlich
Copy link

I can also confirm that this issue happens using dotnet 9. The workaround to surround the shutdown method in a try catch statement works so far. Not using the shtutdown method causes that the process endlessly hangs, so it's required even if it throws the exception above.

It would be great if this issue could be fixed. It's not a show-stopper (if you aware of this issue), but it's definitely not elegant.

AMArostegui added a commit to AMArostegui/SpacyDotNet that referenced this issue Apr 24, 2025
@aba-hb
Copy link

aba-hb commented Apr 25, 2025

It's possible to create your own 'NullFormatter' as a replacement, I've tested this using NET 9.0 and the most recent NuGet release of Python.NET (3.0.5) and it didn't cause any issues yet. This is probably not a good idea, so use on your own risk. Out of all possible solutions, I felt like this is the 'cleanest' one. 😅

#pragma warning disable SYSLIB0011
public class NullFormatter : IFormatter
#pragma warning restore SYSLIB0011
{
    public SerializationBinder Binder { get; set; }
    public StreamingContext Context { get; set; }
    #pragma warning disable SYSLIB0050
    public ISurrogateSelector SurrogateSelector { get; set; }
    #pragma warning restore SYSLIB0050

    public object Deserialize(Stream serializationStream)
    {
        return null;
    }

    public void Serialize(Stream serializationStream, object graph)
    {
        // ...
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants