GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — BinaryFormatter serialization and deserialization warning which throws an error in .net8 · Issue #2282 · pythonnet/pythonnet

BinaryFormatter serialization and deserialization warning which throws an error in .net8 #2282

New issue
Copy link
New issue
Copy link
Open
Open
BinaryFormatter serialization and deserialization warning which throws an error in .net8#2282
Copy link

Description

@RobertClapham
RobertClapham
opened on Nov 16, 2023
Issue body actions

Environment

  • Pythonnet version: 3.0.3
  • Python version: 3.9
  • Operating System: Windows 11
  • .NET Runtime: .net8 (release version 16/11/23)

Details

  • When shutting down the the PythonEngine via a Dispose method on the impermentation class, the error occurs at the PythonEngine.Shutdown(); method and throws the error System.NotSupportedException: BinaryFormatter serialization and deserialization are disabled within this application (see trace below). The same code worked in .net7 without any issues, the error message leads to this description

  • https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

  • Proir to the Shutdown error the pythonnet works correctly and calls python functions and returns the expected results

  • The resolution is to add true to the .csproj file

  • <PropertyGroup>
      <TargetFramework>net8.0</TargetFramework>
      <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
     </PropertyGroup>
    

    TODO

  • _logger.Log is to to trace the point of failure

  • _logger.Log(LogLevel.Error, "Shutting down Python engine"); runs

  • it crashes at the PythonEngine.Shutdown(); method

  • _logger.Log(LogLevel.Error, "Python engine shut down"); does not run

    private void Dispose(bool disposing)
    {
    _logger.Log(LogLevel.Error, "Dispose");
    if (_disposed) return;
    if (disposing)
    {
    _logger.Log(LogLevel.Error, "Shutting down Python engine");
    PythonEngine.Shutdown();
    _logger.Log(LogLevel.Error, "Python engine shut down");
    }
    _disposed = true;
    }

    print('TODO')
  • System.NotSupportedException: BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatt...

System.NotSupportedException
BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information.
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at Python.Runtime.RuntimeData.Stash()
at Python.Runtime.Runtime.Shutdown()
at Python.Runtime.PythonEngine.Shutdown()
at EcgAi.Training.Infrastructure.Python.PythonEnvironment.Dispose(Boolean disposing) in C:\Data\Rider\EcgAi.Training\Src\EcgAi.Training.Infrastructure.Python\PythonEnvironment.cs:line 113
at EcgAi.Training.Infrastructure.Python.PythonEnvironment.Dispose() in xxxxxxxxxxxxxxxxxxxxxxxxx

    print('TODO')
Reacted by Xpl0itR, Charles Zhang, heartacker, Kelly Ann, Thomas M. Atwood, CFA, zejji, KoalaBear84, hhmmjjnn and Jacob Svensson

Activity

  1. TimIrwin26 commented on Dec 17, 2023

    @TimIrwin26
    TimIrwin26
    on Dec 17, 2023
    More actions

    The issue happens in RuntimeData.Stash --

        var runtimeStorage = new PythonNetState
        {
            Metatype = MetaType.SaveRuntimeData(),
            ImportHookState = ImportHook.SaveRuntimeData(),
            Types = TypeManager.SaveRuntimeData(),
            Classes = ClassManager.SaveRuntimeData(),
            SharedObjects = SaveRuntimeDataObjects(),
        };
    
        IFormatter formatter = CreateFormatter();
        var ms = new MemoryStream();
        formatter.Serialize(ms, runtimeStorage);
       internal static IFormatter CreateFormatter()
       {
           return FormatterType != null ?
               (IFormatter)Activator.CreateInstance(FormatterType)
               : new BinaryFormatter();
       }

    While there is an option to set another formatter, it's not used and expected to be of type IFormatter which is problematic.

  2. fsz1987 commented on Jan 1, 2024

    @fsz1987
    fsz1987
    on Jan 1, 2024
    More actions

    Pythonnet use BinaryFormatter. and it is deprecated in .net 8.
    create an instance of BinaryFormatter will cause an error.

    you can set RuntimeData.FormatterType to your custom formatter to get it work.

    if you dont want write a custom formatter, then add this line

    AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", true);

    before you call PythonEngine.Shutdown to temporary enable BinaryFormatter.

    after PythonEngine.Shutdown. call

    AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", false);

    to disable BinaryFormatter

    Reacted by gerneio, Luiz Henrique Cassettari, Pasakorn Tiwatthanont, SEOKWON HONG, Thomas M. Atwood, CFA and Daniel Hüsken
  3. amishratnasthapit commented on Feb 19, 2024

    @amishratnasthapit
    amishratnasthapit
    on Feb 19, 2024
    More actions

    Facing same issue and using work around currently. But .NET 9 is getting rid of Binary Formatter altogether. So this needs to be fixed.

    Reacted by Shawn Eddy, JJOL, SEOKWON HONG, Thomas M. Atwood, CFA, clint21.eth ⚡️ and Rijno
  4. glopesdev
    added a commit that references this issue on Jun 21, 2024

    Avoid shutdown exception due to deprecated API

    2ff9df0
  5. AtwoodTM commented on Aug 31, 2024

    @AtwoodTM
    AtwoodTM
    on Aug 31, 2024
    More actions

    This is a big issue as the binary formatter was deprecated as it is a serious security issue.

    To replace the formatter, there looks to be two high performance/low latency alternatives... Protobuf and MessagePack. Any preference which to use (MessagePack will be slightly faster than Protobuf, but Protobuf is more well known)?

  6. lostmsu commented on Aug 31, 2024

    @lostmsu
    lostmsu
    on Aug 31, 2024
    Member
    More actions

    No formatter is really needed unless you are using .NET Framework. The only place where formatter is used is app domain restart, and app domains are not available in later .NETs

  7. filmor commented on Sep 19, 2024

    @filmor
    filmor
    on Sep 19, 2024
    Member
    More actions

    This should be fixed now.

  8. filmor
    closed this as completedon Sep 19, 2024
  9. nwoolls commented on Oct 21, 2024

    @nwoolls
    nwoolls
    on Oct 21, 2024
    More actions

    @filmor is this fix available on NuGet? I'm still seeing this issue with the latest 3.1 preview version on NuGet.

  10. Lemur8063 commented on Nov 1, 2024

    @Lemur8063
    Lemur8063
    on Nov 1, 2024
    More actions

    @filmor is this fix available on NuGet? I'm still seeing this issue with the latest 3.1 preview version on NuGet.

    no

  11. mmsbld
    added a commit that references this issue on Nov 3, 2024

    BinaryFormatter serialization - security risk - discussion: the Pytho…

    7fc1d1f
  12. Baumx1234 commented on Dec 17, 2024

    @Baumx1234
    Baumx1234
    on Dec 17, 2024
    More actions

    I'm using Nuget Version 3.0.5 and .Net Version 8.0 and still got the issue.

  13. filmor
    reopened this on Dec 17, 2024
  14. filmor commented on Dec 17, 2024

    @filmor
    filmor
    on Dec 17, 2024
    Member
    More actions

    Yeah, this is more difficult to fix than anticipated.

  15. WallucePinkham commented on Jan 27, 2025

    @WallucePinkham
    WallucePinkham
    on Jan 27, 2025
    More actions

    Is there an update on this issues, by any chance?

  16. leftos commented on Feb 10, 2025

    @leftos
    leftos
    on Feb 10, 2025
    More actions

    I was struggling with this, tried to use all sorts of BinaryFormatter NuGet packages to get pythonnet to be happy, and nothing worked...

    But then I came across this:
    https://learn.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support

    All I had to do was implement that PluginLoadContext class...
    (note that I changed it ever so slightly from the example in the linked article to enable unloading which is off by default, because of its associated cost)

        class PluginLoadContext : AssemblyLoadContext
        {
            private AssemblyDependencyResolver _resolver;
    
            public PluginLoadContext(string pluginPath) : base(true) // passing true to the base constructor enables unloading
            {
                _resolver = new AssemblyDependencyResolver(pluginPath);
            }
    
            protected override Assembly Load(AssemblyName assemblyName)
            {
                string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
                if (assemblyPath != null)
                {
                    return LoadFromAssemblyPath(assemblyPath);
                }
    
                return null;
            }
    
            protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
            {
                string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
                if (libraryPath != null)
                {
                    return LoadUnmanagedDllFromPath(libraryPath);
                }
    
                return IntPtr.Zero;
            }
        }

    ...and then change up my code a bit to have a PluginLoadContext instance and use that to load the assembly and unload it (using IDisposable), and I was finally able to keep reusing the same assembly, without pythonnet throwing an exception that it's still initialized when I would invoke the assembly's constructor on the very first Runtime.PythonDLL = ... line.

        public class PythonTTSProvider : ITTSProvider // ITTSProvider : IDisposable
        {
            private readonly dynamic _pythonTTSLib;
            private static PluginLoadContext? _pluginLoadContext;
    
            private PythonTTSProvider(dynamic pythonTTSLib)
            {
                _pythonTTSLib = pythonTTSLib;
    
               // ...
            }
    
            public static ITTSProvider? New()
            {
                string assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"PythonTTS\PythonTTS.dll");
                _pluginLoadContext = new(assemblyPath);
                dynamic? ttsLib = null;
                if (File.Exists(assemblyPath))
                {
                    var assembly = _pluginLoadContext.LoadFromAssemblyPath(assemblyPath);
                    var type = assembly.GetType("PythonTTS.KokoroTTS");
                    if (type != null)
                    {
                        ttsLib = Activator.CreateInstance(type, [Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"PythonTTS\python3.12.9\python312.dll")]);
                    }
                }
                else
                {
                    throw new FileNotFoundException($"PythonTTS library not found. Please ensure you have extracted the PythonTTS archive.\n\nFile path expected: {assemblyPath}");
                }
                return ttsLib != null ? new PythonTTSProvider(ttsLib) : null;
            }
    
            // ...
    
            public void Dispose()
            {
                _pluginLoadContext?.Unload();
                GC.SuppressFinalize(this);
            }

    I was so happy to finally get this to work after 2 days of struggling with it.

    Hopefully this helps someone else as well.

    Reacted by Victor
  17. sharpSteff commented on Feb 11, 2025

    @sharpSteff
    sharpSteff
    on Feb 11, 2025
    More actions

    I created a custom JsonBinaryFormater, based on good old Newtonsoft.Json for this issue:

    public class JsonBinaryFormatter : IFormatter
    {
        private readonly JsonSerializer_serializer;
    
        public JsonFormatter()
        {
            _serializer = new JsonSerializer();
        }
    
        /// <inheritdoc />
        public SerializationBinder Binder { get; set; }
    
        /// <inheritdoc />
        public StreamingContext Context { get; set; }
    
        /// <inheritdoc />
        public ISurrogateSelector SurrogateSelector { get; set; }
    
        /// <inheritdoc />
        public object Deserialize(Stream serializationStream)
        {
             using var sr = new StreamReader(stream, Encoding.UTF8, true, 1024, true);
             using var jsonTextReader = new JsonTextReader(sr);
             return _serializer.Deserialize(jsonTextReader);
        }
    
        /// <inheritdoc />
        public void Serialize(Stream serializationStream, object graph)
        {
            using var sr = new StreamWriter(serializationStream, Encoding.UTF8, 1024, true);
            _serializer.Serialize(sr, graph);
        }
    }
    

    It can be used via

    Python.Runtime.RuntimeData.FormatterType = typeof(JsonFormatter);

    So far I have no issues

  18. novitk commented on Aug 3, 2025

    @novitk
    novitk
    on Aug 3, 2025
    More actions

    This is not a true solution, but to silence the exception you can just override the formatter with NoopFormatter:
    Python.Runtime.RuntimeData.FormatterType = typeof(Python.Runtime.NoopFormatter);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402520 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.