You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apologies for the late reply. Yes, if we're shutting down for the last time, then there is no need to stash anything. If I recall correctly, it used to be that way before when there was still multiple modes. But I'm not sure about garbage collection, I've had some issues in the past (crashing on shutdown?) if it wasn't run correctly.
@lostmsu@BadSingleton Now that issues like #2107 show up because BinaryFormatter.Serialize has been hard-deprecated in .NET 7, we need to do somethhing. How about making Shutdown() behave like it used to (no stashing) and adding a new ShutdownAllowRestart or something like that?
@benoithudson what is Unity on now? I thought it relies on AppDomain, and AppDomain is not supported in .NET Core/6+. Without AppDomain, I do not think one needs to call Shutdown at all. What should be done instead perhaps is ability to reload individual types.
I faced the same problem (Pythonnet 3.0.1, .NET Framework 4.7.2). In my app I have a window with the python code editor. I call PythonEngine.Initialize() when the user opens it, and the PythonEngine.Shotdown() when closing the window.
After executing simple scripts, the window closes with a small but noticeable delay. When executing scripts that create more complex objects, for example, matplayotlib figures, the delay increases to tens or even hundreds of seconds. I can call PythonEngine.Shotdown() not when closing the editor window, but when closing the application. But for now this only shifts the problem and does not solve it.
Unfortunately, I wasn’t able to find the official position on this subject in the documentation. The fact that many people use Pythonnet suggest that there is a way of bypass, because without it the issue looks serious. @dclaudeone11 Did you manage to find a temporary solution?
Without AppDomain, I do not think one needs to call Shutdown at all
@lostmsu First of all, thank you and other contributors for such a useful library.
Could you please explain what exactly is considered as a right way to stop Pythonnet (or app that uses it) for today? If I do not call PythonEngine.Shotdown() at all, after closing the main window of the program, a working process remains, which is obviously unacceptable. Given the popularity of this thread in the last days, it seems that many more people would be grateful for your official commentary, not only me.
@AlexGilmor If you want to shut down Python, use Shutdown. The slowness is due to to multiple garbage collection rounds and (potentially contributing, but not the only factor) the runtime stashing that was introduced to allow for AppDomain switching.
@nlogozzo Since you are not actually using the stashing, you can try setting a no-op formatter:
We are embedding Python in a .NET app using pythonnet.
The call to PythonEngine.Shutdown() at the exit of this app lasts for more than 2 minutes.
Looking at the shutdown with a profiler shows that most of the time is spent in Runtime.TryCollectingGarbage().
Looks like the more memory is allocated on the C# side the more the shutdown (i.e. calls to GC.Collect()) is slow.
Minimal, Complete, and Verifiable example
usingPython.Runtime;namespaceTest;staticclassProgram{staticvoidMain(){varmem=newList<Array>();Runtime.PythonDLL=@$"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\AppData\Local\Programs\Python\Python39\python39.dll";PythonEngine.Initialize();varthreadState=PythonEngine.BeginAllowThreads();using(Py.GIL()){using(varscope=Py.CreateScope()){scope.Set("a",1);scope.Set("b",2);scope.Exec("result = a + b");varresult=scope.Get("result").As<int>();Console.WriteLine($"Sum = {result}");}}// allocate dotnet-managed memory unrelated to pythonnetvarrnd=newRandom();for(vari=0;i<100_000_000;++i){mem.Add(newbyte[rnd.Next(1,10)]);}PythonEngine.EndAllowThreads(threadState);Console.WriteLine("Shutdown start");varstart=DateTime.Now;PythonEngine.Shutdown();vardiff=DateTime.Now-start;Console.WriteLine($"Shutdown stop {diff.TotalSeconds}");}}
Typical output:
Sum = 3
Shutdown start
Shutdown stop 61.6796983
Your issue does not occur when the project is ran in .NET 7 using a Release configuration. When ran in Debug configuration, the shutdown does indeed slow down significantly - from 0.08 seconds up to 63 seconds.
public class NoopFormatter : IFormatter {
public object Deserialize(Stream s) => throw new NotImplementedException();
public void Serialize(Stream s, object o) {}
public SerializationBinder Binder { get; set; }
public StreamingContext Context { get; set; }
public ISurrogateSelector SurrogateSelector { get; set; }
}
Activity
filmor commentedon Nov 22, 2022
This would probably be helped by handling #1781.
If we are finally shutting down, we don't actually have to stash anything, so we also shouldn't try to clean up garbage, right @lostmsu @BadSingleton ?
fischja commentedon Feb 16, 2023
Any updates on this @filmor ?
BadSingleton commentedon Feb 17, 2023
Apologies for the late reply. Yes, if we're shutting down for the last time, then there is no need to stash anything. If I recall correctly, it used to be that way before when there was still multiple modes. But I'm not sure about garbage collection, I've had some issues in the past (crashing on shutdown?) if it wasn't run correctly.
filmor commentedon Feb 20, 2023
@lostmsu @BadSingleton Now that issues like #2107 show up because
BinaryFormatter.Serializehas been hard-deprecated in .NET 7, we need to do somethhing. How about makingShutdown()behave like it used to (no stashing) and adding a newShutdownAllowRestartor something like that?lostmsu commentedon Feb 20, 2023
@filmor @BadSingleton do we even need to support restart after shutdown on .NET 7?
BadSingleton commentedon Feb 20, 2023
I've been out of the .NET loop for a few months, why wouldn't we need to support it?
Otherwise, I don't think it has to be
BinaryFormatter, as long as the behaviour is the same(?)benoithudson commentedon Feb 20, 2023
Unity is moving to .NET 7 next year supposedly (in large part to support Span). So, it would be best if it were still supported.
https://blog.unity.com/technology/unity-and-net-whats-next
For the original comment: do we actually need to call Shutdown on shutdown? If not, that would save a lot of time.
lostmsu commentedon Feb 20, 2023
@benoithudson what is Unity on now? I thought it relies on
AppDomain, andAppDomainis not supported in .NET Core/6+. WithoutAppDomain, I do not think one needs to callShutdownat all. What should be done instead perhaps is ability to reload individual types.nlogozzo commentedon Feb 23, 2023
Hi, anyway I can work around this issue for now?
AlexGilmor commentedon Feb 23, 2023
I faced the same problem (Pythonnet 3.0.1, .NET Framework 4.7.2). In my app I have a window with the python code editor. I call PythonEngine.Initialize() when the user opens it, and the PythonEngine.Shotdown() when closing the window.
After executing simple scripts, the window closes with a small but noticeable delay. When executing scripts that create more complex objects, for example, matplayotlib figures, the delay increases to tens or even hundreds of seconds. I can call PythonEngine.Shotdown() not when closing the editor window, but when closing the application. But for now this only shifts the problem and does not solve it.
Unfortunately, I wasn’t able to find the official position on this subject in the documentation. The fact that many people use Pythonnet suggest that there is a way of bypass, because without it the issue looks serious. @dclaudeone11 Did you manage to find a temporary solution?
@lostmsu First of all, thank you and other contributors for such a useful library.
Could you please explain what exactly is considered as a right way to stop Pythonnet (or app that uses it) for today? If I do not call PythonEngine.Shotdown() at all, after closing the main window of the program, a working process remains, which is obviously unacceptable. Given the popularity of this thread in the last days, it seems that many more people would be grateful for your official commentary, not only me.
filmor commentedon Feb 23, 2023
@AlexGilmor If you want to shut down Python, use
Shutdown. The slowness is due to to multiple garbage collection rounds and (potentially contributing, but not the only factor) the runtime stashing that was introduced to allow forAppDomainswitching.@nlogozzo Since you are not actually using the stashing, you can try setting a no-op formatter:
nlogozzo commentedon Feb 23, 2023
That worked...thanks!
kikaragyozov commentedon Mar 30, 2023
Your issue does not occur when the project is ran in .NET 7 using a Release configuration. When ran in Debug configuration, the shutdown does indeed slow down significantly - from 0.08 seconds up to 63 seconds.
This does not fix the issue when the code is ran in Debug configuration under .NET 7.
gitlsl commentedon Aug 30, 2023
v3.0.2 same question, NoopFormatter has no effact