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
using System;
using System.Collections.Generic;
using Python.Runtime;
namespace TestPythonnet
{
class Program
{
static void Main(string[] args)
{
// my base environment
// also added this to top of PATH in project settings
var pathToBaseEnv = @"C:\Users\myuser\AppData\Local\Programs\Python\Python38";
Environment.SetEnvironmentVariable("PYTHONNET_PYVER", "3.8", EnvironmentVariableTarget.Process);
// this call has no effect
PythonEngine.SetNoSiteFlag();
// if you swap this call with previous line, it will work
PythonEngine.PythonHome = pathToBaseEnv;
PythonEngine.Initialize();
using (Py.GIL())
{
Console.WriteLine($"sys.executable: {sys.executable}");
Console.WriteLine($"sys.prefix: {sys.prefix}");
Console.WriteLine($"sys.base_prefix: {sys.base_prefix}");
Console.WriteLine($"sys.exec_prefix: {sys.exec_prefix}");
Console.WriteLine($"sys.base_exec_prefix: {sys.base_exec_prefix}");
Console.WriteLine("sys.path:");
foreach (var p in sys.path)
{
Console.WriteLine(p);
}
Console.WriteLine();
}
PythonEngine.Shutdown();
}
}
}
In fact, one can workaround the issue by adding any access to the PythonEngine API which uses the DLL before setting the flag, e.g.
var version = PythonEngine.Version;
PythonEngine.SetNoSiteFlag();
The root cause appears to be that the reference count on the DLL is sent to zero after setting Py_NoSiteFlag, so the DLL is unloaded and reloaded by the Delegate class with the original value of Py_NoSiteFlag=0.
Snip from Python.Runtime.Runtime (runtime.cs) with my added comments.
internal static void SetNoSiteFlag()
{
var loader = LibraryLoader.Instance;
IntPtr dllLocal = IntPtr.Zero;
if (_PythonDll != "__Internal")
{
dllLocal = loader.Load(_PythonDll);
if (dllLocal == IntPtr.Zero)
{
throw new Exception($"Cannot load {_PythonDll}");
}
}
try
{
Py_NoSiteFlag = loader.GetFunction(dllLocal, "Py_NoSiteFlag");
Marshal.WriteInt32(Py_NoSiteFlag, 1); // This works, I can Marshal.ReadInt32 with Immediate window in Debug and get 1
}
finally
{
if (dllLocal != IntPtr.Zero)
{
loader.Free(dllLocal); // if nobody else loaded _PythonDll, it will potentially get unloaded here :-(
}
}
}
If there was a crash, please include the traceback here.
N/A
The text was updated successfully, but these errors were encountered:
My suggested fix would be to defer the actual setting of Py_NoSiteFlag in the DLL and perform it in Runtime.Initialize after we can be sure the DLL has been loaded and attached to the delegates.
Additionally, it would be nice to implement the PEP 587 configuration API on available Python versions (3.8+) which would allow complete control of the embedded python environment, including effective command line options.
Uh oh!
There was an error while loading. Please reload this page.
Environment
Details
Describe what you were trying to get done.
I am trying to disable automatic site run in order to setup a custom virtualenv path.
What commands did you run to trigger this issue? If you can provide a
Minimal, Complete, and Verifiable example
this will help us understand the issue.
Result:
The site packages are still added.
If you swap order of
PythonEngine.SetNoSiteFlag();
andPythonEngine.PythonHome = pathToBaseEnv;
, it worksNo site folders added to the path.
In fact, one can workaround the issue by adding any access to the PythonEngine API which uses the DLL before setting the flag, e.g.
The root cause appears to be that the reference count on the DLL is sent to zero after setting Py_NoSiteFlag, so the DLL is unloaded and reloaded by the Delegate class with the original value of Py_NoSiteFlag=0.
Snip from Python.Runtime.Runtime (runtime.cs) with my added comments.
N/A
The text was updated successfully, but these errors were encountered: