C#通过Pythonnet调用虚拟环境Python脚本报缺失encodings模块错误
问题原因
首先回答你关于python38.dll的疑问:
- 用Python自带venv创建的虚拟环境默认不会存放python38.dll,这个文件不需要额外生成,它始终位于你最初安装Python 3.8.9的根目录下。虚拟环境本质是一套路径映射规则,运行时依赖基础Python安装目录的核心运行时文件,你之前手动复制dll到虚拟环境目录的操作完全多余,甚至可能引发dll加载冲突。
- 你之前设置的python38.dll路径本身是正确的,反复调整这个配置的执行顺序解决不了问题,错误根源不在dll加载,而在Python解释器的标准库路径配置错误。
你遇到的No module named 'encodings'错误核心原因是PYTHONHOME指向错误:你把PYTHONHOME指向了虚拟环境目录,但虚拟环境的Lib目录下只保存了你后续安装的第三方依赖,Python核心标准库(包括encodings这个解释器启动必须加载的模块)全部存放在基础Python安装目录的Lib文件夹下。从你贴的错误日志可以看到,初始化时sys.base_prefix、sys.prefix都是空值,说明解释器根本没定位到基础Python的安装位置,自然找不到核心模块。
修正代码
调整环境变量和引擎配置逻辑,核心是把PYTHONHOME指向基础Python安装目录,同时把所有依赖的库路径加入PYTHONPATH,修正后的代码如下:
// 基础Python 3.8安装根目录 var basePythonPath = @"C:\Users\ardiiva\AppData\Local\Programs\Python\Python38"; // 虚拟环境根目录 var venvPath = @"C:\rebrandingmanager\CFGRebrandingPythonManager\codice\venv"; // 自定义Python脚本存放目录(你的TestPy.py所在的位置) var customScriptPath = @"C:\rebrandingmanager\CFGRebrandingPythonManager\codice"; // 配置Python DLL路径,必须在PythonEngine初始化前设置 Runtime.PythonDLL = Path.Combine(basePythonPath, "python38.dll"); Environment.SetEnvironmentVariable("PYTHONNET_PYDLL", Runtime.PythonDLL, EnvironmentVariableTarget.Process); // 拼接PATH环境变量,加入所有依赖的二进制目录 var currentPath = Environment.GetEnvironmentVariable("PATH")?.TrimEnd(';') ?? ""; var pathEntries = new List<string> { currentPath, basePythonPath, Path.Combine(basePythonPath, "Scripts"), venvPath, Path.Combine(venvPath, "Scripts") }; Environment.SetEnvironmentVariable("PATH", string.Join(";", pathEntries.Where(p => !string.IsNullOrEmpty(p))), EnvironmentVariableTarget.Process); // PYTHONHOME必须指向基础Python安装目录,不能指向虚拟环境 Environment.SetEnvironmentVariable("PYTHONHOME", basePythonPath, EnvironmentVariableTarget.Process); // 拼接PYTHONPATH,覆盖基础标准库、第三方包、自定义脚本三类路径 var pythonPathEntries = new List<string> { Path.Combine(basePythonPath, "Lib"), Path.Combine(basePythonPath, "Lib", "site-packages"), Path.Combine(venvPath, "Lib", "site-packages"), customScriptPath }; var pythonPath = string.Join(";", pythonPathEntries); Environment.SetEnvironmentVariable("PYTHONPATH", pythonPath, EnvironmentVariableTarget.Process); // 初始化Python引擎 PythonEngine.PythonHome = basePythonPath; PythonEngine.PythonPath = pythonPath; PythonEngine.Initialize(); using (Py.GIL()) { // 导入模块时不要加.py后缀 dynamic testModule = Py.Import("TestPy"); testModule.add_watermark("CIAOOOOO", "KAKAKAKAKAKAK.pdf", "RG-39119_002_A_001.pdf"); }
排查注意点
- 确保C#项目的生成平台目标和安装的Python位数一致:64位Python对应x64平台目标,32位Python对应x86平台目标,位数不匹配会导致各类隐性加载错误。
- 导入自定义模块时不要带
.py后缀,Py.Import("TestPy")才是正确写法。 - 自定义Python脚本所在的目录必须加入PYTHONPATH,否则解释器无法定位到你的自定义模块。
- 不需要手动复制python38.dll到虚拟环境目录,保持dll在原始Python安装目录即可,避免出现dll依赖查找错误。
内容的提问来源于stack exchange,提问作者exrezzo
相关产品推荐
相关产品推荐

