You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Python.NET配置virtualenv虚拟环境解决模块导入报错

C#加载virtualenv虚拟环境运行Python脚本问题解决方案

基于IronPython的初始尝试问题

最早尝试使用IronPython加载virtualenv虚拟环境执行Python脚本,实现代码如下:

var eng = IronPython.Hosting.Python.CreateEngine();
var scope = eng.CreateScope();

// 加载虚拟环境搜索路径
ICollection<string> searchPaths = eng.GetSearchPaths();
searchPaths.Add(@"/Users/Desktop/CSharpProjects/demo1/.venv/lib");
searchPaths.Add(@"/Users/Desktop/CSharpProjects/demo1/.venv/lib/site-packages");
searchPaths.Add(AppDomain.CurrentDomain.BaseDirectory);
eng.SetSearchPaths(searchPaths);

string file = @"script.py";
eng.ExecuteFile(file, scope);

运行后抛出导入异常:

Unhandled exception. IronPython.Runtime.Exceptions.ImportException: No module named 'numpy'

待执行的Python脚本在手动激活虚拟环境的终端中可正常运行,脚本内容:

import numpy as np

def name(a, b=1):
    return np.add(a,b)

切换Python.NET后的报错问题

由于IronPython3对带C扩展的CPython第三方库兼容性极差,无法支持numpy这类库,因此改用Python.NET实现,使用的NuGet包为Pythonnet 3.0.0-preview2022-06-27预览版。
初始调用系统全局Python 3.7环境时功能正常,需要调整代码加载位于C:\envs\venv2路径的virtualenv虚拟环境,初始尝试的实现代码如下:

using Python.Runtime;
using System;
namespace ConsoleApp1
{
    public class PythonOperation
    {
        PyModule scope;

        public void Initialize()
        {
            Runtime.PythonDLL = @"C:\\Python37\python37.dll";

            string pathToVirtualEnv = @"C:\envs\venv2";
            string pathToPython = @"C:\Python37\";

            Environment.SetEnvironmentVariable("PATH", pathToPython, 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);
    
            PythonEngine.Initialize();
            scope = Py.CreateScope();
            PythonEngine.BeginAllowThreads();
        }

        public void Execute()
        {
            using (Py.GIL())
            {

            }
        }
    }
}

运行上述代码抛出致命初始化错误:

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


正确配置实现方案

No module named 'encodings'报错的核心原因是环境变量配置逻辑错误:virtualenv创建的虚拟环境本身不包含完整的Python标准库运行时,仅做了依赖隔离,PYTHONHOME直接指向虚拟环境路径会导致Python运行时找不到基础标准库模块。
正确配置逻辑如下:

  1. 路径参数修正:PYTHONHOME必须指向创建虚拟环境时使用的基础Python安装根目录,不能指向虚拟环境路径;虚拟环境的site-packages路径仅作为搜索路径追加到PYTHONPATH即可。
  2. 修正路径转义错误:原代码中Runtime.PythonDLL的路径字符串在@前缀下多余转义,会导致dll加载路径错误。
  3. PATH变量配置:不要覆盖进程原有PATH值,将基础Python根目录、基础Python下的DLLs目录、虚拟环境的Scripts目录追加到PATH头部,保证运行时依赖的dll可以正常寻址。
  4. 严格遵守初始化顺序:先完成所有环境变量配置、指定正确的Python dll路径,再调用PythonEngine.Initialize()完成引擎初始化。

修正后的可运行代码:

using Python.Runtime;
using System;
namespace ConsoleApp1
{
    public class PythonOperation
    {
        private PyModule _scope;

        public void Initialize()
        {
            // 指定创建虚拟环境对应的基础Python的dll路径,注意逐字字符串不需要双反斜杠转义
            Runtime.PythonDLL = @"C:\Python37\python37.dll";

            // 配置基础Python路径、虚拟环境路径
            string venvPath = @"C:\envs\venv2";
            string basePythonPath = @"C:\Python37";

            // 配置进程PATH变量,追加Python相关路径,不覆盖原有值
            var currentPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
            var newPath = $"{basePythonPath};{basePythonPath}\\DLLs;{venvPath}\\Scripts;{currentPath}";
            Environment.SetEnvironmentVariable("PATH", newPath, EnvironmentVariableTarget.Process);
            
            // PYTHONHOME必须指向基础Python安装根目录
            Environment.SetEnvironmentVariable("PYTHONHOME", basePythonPath, EnvironmentVariableTarget.Process);
            
            // PYTHONPATH同时包含基础Python标准库路径、基础Python全局包路径、虚拟环境库路径、虚拟环境第三方包路径
            string pythonPath = $"{basePythonPath}\\Lib;{basePythonPath}\\Lib\\site-packages;{venvPath}\\Lib;{venvPath}\\Lib\\site-packages";
            Environment.SetEnvironmentVariable("PYTHONPATH", pythonPath, EnvironmentVariableTarget.Process);

            // 同步设置PythonEngine参数
            PythonEngine.PythonHome = basePythonPath;
            PythonEngine.PythonPath = pythonPath;

            // 初始化引擎
            PythonEngine.Initialize();
            _scope = Py.CreateScope();
            PythonEngine.BeginAllowThreads();
        }

        public void Execute(string scriptPath)
        {
            using (Py.GIL())
            {
                // 执行脚本示例
                _scope.ExecFile(scriptPath);
                // 调用脚本内函数示例
                // dynamic calcFunc = _scope.Get("name");
                // var res = calcFunc(2, 3);
            }
        }
    }
}

注意事项

  • IronPython是.NET平台重新实现的Python运行时,不支持CPython生态下带C扩展的第三方库(numpy、pandas、opencv等均属于此类),这类场景必须使用Python.NET实现互操作。
  • 项目编译的平台目标必须和本地安装的Python位数一致:64位Python对应x64编译目标,32位Python对应x86编译目标,否则会出现dll加载失败、入口点找不到的问题。
  • Python 3.8+版本创建的虚拟环境目录层级可能存在细微差异,配置前先核对本地虚拟环境下Lib、site-packages的实际路径,按实际情况调整参数即可。
  • 所有Python相关的路径配置必须在PythonEngine.Initialize()调用前完成,初始化完成后再修改路径参数不会生效。

内容的提问来源于stack exchange,提问作者Joseph Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:27:22