Description
Environment
- Pythonnet version: 3.0.0-preview2021-06-04
- Python version: 3.9.1 (tags/v3.9.1:1e5d33e, Dec 7 2020, 17:08:21) [MSC v.1927 64 bit (AMD64)]
- Operating System: Windows 10 20H2
- .NET Runtime: 5.0.301
Details
according to #984 .NET Core is supported, which I hope includes .NET 5.0
according to #1389 Python 3.9 is supported in pythonnet 2.5, though I was unable to find 2.5 on nuget, so I went with a 3.0 preview in the hopes that it will work too.
Describe what you were trying to get done.
Embed python in a C# application with a virtual environment (venv) and import a module from it.
I have set up a virtual environment at C:\Users\felk\venv39
and verified that it works and I can use modules that are available in the venv but not globally:
PS C:\Users\felk> python -c 'import chat_downloader; print(True)'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'chat_downloader'
PS C:\Users\felk> .\venv39\Scripts\Activate.ps1
(venv39) PS C:\Users\felk> python -c 'import chat_downloader; print(True)'
True
According to the wiki this is the code to get virtual environments working:
var pathToVirtualEnv = @"path\to\env";
// be sure not to overwrite your existing "PATH" environmental variable.
var path = Environment.GetEnvironmentVariable("PATH").TrimEnd(';');
path = string.IsNullOrEmpty(path) ? pathToVirtualEnv : path + ";" + pathToVirtualEnv;
Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PATH", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONPATH", $"{pathToVirtualEnv}\\Lib\\site-packages;{pathToVirtualEnv}\\Lib", EnvironmentVariableTarget.Process);
PythonEngine.PythonHome = pathToVirtualEnv;
PythonEngine.PythonPath = Environment.GetEnvironmentVariable("PYTHONPATH", EnvironmentVariableTarget.Process);
However it is not clear to me what comes after that, most importantly where do I call PythonEngine.Initialize();
, so I attempted to piecemeal something together:
- Calling
PythonEngine.Initialize();
after the above snipped causes the application to crash without an exception, which I suspected is a segfault due to threading issues - Not calling it at all crashes the program in the same way upon first usage of any python within C#
- Calling it just before setting
PythonEngine.PythonHome
andPythonEngine.PythonPath
seems to work, in a sense that the application does not crash and calls into python from C# are possible.
However, when I try to import a module present in the virtual environment, it is not being found. I can observe that the venv path is part of PythonEngine.PythonPath
but not part of sys.path
by checking after setting PythonEngine.PythonPath
:
dynamic sys = Py.Import("sys");
Console.WriteLine(sys.path);
Console.WriteLine(PythonEngine.PythonPath);
this results in
['C:\\Program Files\\Python39\\python39.zip', 'C:\\Program Files\\Python39\\Lib', 'C:\\Program Files\\Python39\\DLLs', 'S:\\projects\\myproject\\bin\\Debug\\net5.0', 'C:\\Users\\felk\\AppData\\Roamin
g\\Python\\Python39\\site-packages', 'C:\\Program Files\\Python39', 'C:\\Program Files\\Python39\\lib\\site-packages', 'C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\5.0.7\\']
C:/Users/felk/venv39/Lib/site-packages;C:/Users/felk/venv39/Lib;
This seems to be unrelated, but I also removed this line from the wiki's example as it seems nonsensical to override the PATH
with the venv path if it was just set to the correctly appended one a line above, and since the comment above literally just said be sure not to overwrite your existing "PATH" environmental variable
:
Environment.SetEnvironmentVariable("PATH", pathToVirtualEnv, EnvironmentVariableTarget.Process);
I also tried appending to PythonEngine.PythonPath
instead of replacing it, as described in #1348 but that had no effect either.