Python.net 3.0.3在Ubuntu22.04调用本地模块失败,Windows11正常
问题概述
开发基于.NET 8的C#应用,使用Python.net 3.0.3调用bin/Debug/net8.0目录下实现两数相乘的Python模块。该应用在Windows 11运行正常,但在Ubuntu 22.04中抛出Python.Runtime.PythonException,提示No module named 'script',且两台机器的文件完全一致。
代码与文件内容
C#主程序代码
namespace PythonLoader { using System; using System.Runtime.InteropServices; using GetSomeInput; using Python.Runtime; public class Program { public static void Main(string[] args) { try { string script = Inputty.GetString("Module name: ", "script", false); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Runtime.PythonDLL = @"C:\Python312\python312.dll"; } else { Runtime.PythonDLL = @"/usr/lib/x86_64-linux-gnu/libpython3.10.so"; } PythonEngine.Initialize(); PythonEngine.BeginAllowThreads(); Console.WriteLine("Using Python DLL : " + Runtime.PythonDLL); Console.WriteLine("Using Python version : " + PythonEngine.Version); Console.WriteLine("Build information : " + PythonEngine.BuildInfo); Console.WriteLine("Compiler : " + PythonEngine.Compiler); Console.WriteLine("Max supported version : " + PythonEngine.MaxSupportedVersion); Console.WriteLine("Min supported version : " + PythonEngine.MinSupportedVersion); Console.WriteLine("Platform : " + PythonEngine.Platform); Console.WriteLine("Program name : " + PythonEngine.ProgramName); Console.WriteLine("Python home : " + PythonEngine.PythonHome); Console.WriteLine("Python path : " + PythonEngine.PythonPath); using (Py.GIL()) { dynamic app = Py.Import(script); Console.WriteLine(app.multiply(2, 4)); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } } }
Python模块文件
script.py:
def multiply(a, b): return a * b
__init__.py:
from script import multiply
上述两个Python文件已复制到输出目录bin/Debug/net8.0。
运行情况对比
Windows 11运行正常
C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0>pythonloader Module name: [script] Using Python DLL : C:\Python312\python312.dll Using Python version : 3.12.2 (tags/v3.12.2:6abddd9, Feb 6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)] Build information : tags/v3.12.2:6abddd9, Feb 6 2024, 21:26:36 Compiler : [MSC v.1937 64 bit (AMD64)] Max supported version : 3.12.2147483647.2147483647 Min supported version : 3.7 Platform : win32 Program name : python Python home : Python path : C:\Python312\python312.zip;C:\Python312\DLLs;C:\Python312\Lib;C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0 8
Ubuntu 22.04运行失败
joel@ubuntu:~/Code/pythontest/bin/Debug/net8.0$ ./pythontest Python filename: [script.py] Using Python DLL : /usr/lib/x86_64-linux-gnu/libpython3.10.so Using Python version : 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] Build information : main, Nov 20 2023, 15:14:05 Compiler : [GCC 11.4.0] Max supported version : 3.12.2147483647.2147483647 Min supported version : 3.7 Platform : linux Program name : python3 Python home : Python path : /usr/lib/python310.zip:/usr/lib/python3.10:/usr/lib/python3.10/lib-dynload:/home/joel/Code/pythontest/bin/Debug/net8.0 Python.Runtime.PythonException: No module named 'script' at Python.Runtime.PythonException.ThrowLastAsClrException() at Python.Runtime.NewReferenceExtensions.BorrowOrThrow(NewReference& reference) at Python.Runtime.PyModule.Import(String name) at Python.Runtime.Py.Import(String name) at PythonLoader.Program.Main(String[] args) in /home/joel/Code/pythontest/Program.cs:line 59
目录内容对比
Windows输出目录
C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0>dir Volume in drive C is OS Volume Serial Number is 541C-D54E Directory of C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0 05/24/2024 08:34 PM <DIR> . 05/24/2024 09:07 AM <DIR> .. 01/11/2024 11:37 AM 322,048 GetSomeInput.dll 10/11/2023 12:15 AM 431,616 Python.Runtime.dll 05/24/2024 02:32 PM 7,378 PythonLoader.deps.json 05/24/2024 08:34 PM 6,656 PythonLoader.dll 05/24/2024 08:34 PM 142,848 PythonLoader.exe 05/24/2024 08:34 PM 10,932 PythonLoader.pdb 05/24/2024 09:17 AM 268 PythonLoader.runtimeconfig.json 05/24/2024 09:16 AM 37 script.py 05/24/2024 03:40 PM 29 __init__.py 05/24/2024 09:21 AM <DIR> __pycache__ 9 File(s) 921,812 bytes 3 Dir(s) 48,029,245,440 bytes free
Ubuntu输出目录
joel@ubuntu:~/Code/pythontest/bin/Debug/net8.0$ ls -la total 860 drwxrwxr-x 2 joel joel 4096 May 24 20:33 . drwxrwxr-x 3 joel joel 4096 May 24 15:41 .. -rwxrw-r-- 1 joel joel 322048 Jan 11 10:32 GetSomeInput.dll -rw-rw-r-- 1 joel joel 31 May 24 15:52 __init__.py -rwxrw-r-- 1 joel joel 431616 Oct 11 2023 Python.Runtime.dll -rwxr-xr-x 1 joel joel 72448 May 24 20:33 pythontest -rw-rw-r-- 1 joel joel 7171 May 24 15:41 pythontest.deps.json -rw-rw-r-- 1 joel joel 6656 May 24 20:33 pythontest.dll -rw-rw-r-- 1 joel joel 10964 May 24 20:33 pythontest.pdb -rw-rw-r-- 1 joel joel 257 May 24 15:41 pythontest.runtimeconfig.json -rw-rw-r-- 1 joel joel 38 May 24 20:31 script.py
解决方案建议
1. 修正模块名输入
从Ubuntu运行日志可见,输入的模块名是script.py,而Py.Import()需要传入不带.py后缀的模块名。运行时直接按回车使用默认值script即可,不要手动添加.py。
2. 强制添加当前目录到Python路径
即使日志显示PythonPath包含当前目录,仍可在代码中手动添加程序所在目录到Python的sys.path,确保模块能被找到:
修改C#代码中using (Py.GIL())块的内容:
using (Py.GIL()) { // 获取程序所在目录 string appDir = AppContext.BaseDirectory; // 导入sys模块并添加路径 dynamic sys = Py.Import("sys"); sys.path.append(appDir); dynamic app = Py.Import("script"); Console.WriteLine(app.multiply(2, 4)); }
3. 统一Python版本(可选)
Windows使用Python 3.12,Ubuntu使用Python 3.10,虽然Python.net 3.0.3支持3.7-3.12版本,但统一Python版本可避免潜在的兼容性问题。可在Ubuntu安装Python 3.12并修改Runtime.PythonDLL路径为对应版本的.so文件。
4. 验证文件权限
确保Ubuntu下script.py和__init__.py有可读权限,当前目录有访问权限。若仍有问题可执行:
chmod 644 script.py __init__.py chmod 755 ~/Code/pythontest/bin/Debug/net8.0
5. 检查工作目录
确认程序运行时的工作目录是输出目录bin/Debug/net8.0。可在代码中添加日志打印当前工作目录:
Console.WriteLine("Current working directory: " + Directory.GetCurrentDirectory());
若工作目录不符,可在运行程序前切换到输出目录,或在代码中手动设置工作目录:
Directory.SetCurrentDirectory(AppContext.BaseDirectory);
内容的提问来源于stack exchange,提问作者joelc

