Skip to content

Using Python.NET with Virtual Environments

Meisterrichter edited this page Aug 12, 2021 · 6 revisions

Using Python.NET with Virtual Environments

This is a simple tutorial on how to use Python.NET with virtual environments, created via Virtualenv, Virtualenvwrapper or Anaconda. Common errors indicating there being an issue with your virtual environment configuration include unable to import modules and external DLLs such as

Fatal Python error: initfsencoding: unable to load the file system codec
ModuleNotFoundError: No module named 'encodings'

and unable to load PythonXXX.dll or Could not load dynamic library 'cublas64_11.dll'; dlerror: cublas64_11.dll not found.

To use your virtual environment, you must configure the environment variables PATH, PYTHONHOME and PYTHONPATH to point to your virtual environment and not to any other python sources. This should be done before setting the python path on the PythonEngine. The PATH environmental variable needs to but updated to include the path to your virtual environment and the PYTHONHOME variable just needs to point to your virtual environment.

var pathToVirtualEnv = @"path\to\env";

var path = Environment.GetEnvironmentVariable("PATH").TrimEnd(';');
path = string.IsNullOrEmpty(path) ? pathToVirtualEnv : path + ";" + pathToVirtualEnv;
Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToVirtualEnv, EnvironmentVariableTarget.Process);            

however PYTHONPATH needs to point to the Lib sub-directory as well as the Lib\site-packages sub-directory.

Environment.SetEnvironmentVariable("PYTHONPATH", $"{pathToVirtualEnv}\\Lib\\site-packages;{pathToVirtualEnv}\\Lib", EnvironmentVariableTarget.Process);            

Once the environment variables have been setup, you can update the PythonHome and the PythonPath on the PythonEngine.

PythonEngine.PythonHome = pathToVirtualEnv;
PythonEngine.PythonPath = Environment.GetEnvironmentVariable("PYTHONPATH", EnvironmentVariableTarget.Process);

Example Code

Here is an example project demonsrtating the necessary configuration.

using System;
using Python.Runtime;

namespace Virtualenv.Example
{
    public class Program
    {
        public void Main()
        {
            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);
        }
    }
}

Related

Here are some related posts with more information.