Python for .NET: 导入错误:没有名为warnings的模块

8 投票
3 回答
6209 浏览
提问于 2025-04-16 10:06

我正在尝试把 Python 2.6 嵌入到 .NET 4.0 中。

根据“Python for .NET”里很简单的说明,我写了一段比较简单的代码,如下所示:

 const string pythonModulePath = @"C:\Projects\PythonImport\PythonImport\test.py";
 Environment.SetEnvironmentVariable("PYTHONHOME", Path.GetDirectoryName(python
 ModulePath));

 PythonEngine.Initialize();

 var oldWorkingDirectory = Directory.GetCurrentDirectory();
 var currWorkingDirectory = Path.GetDirectoryName(pythonModulePath);

 Directory.SetCurrentDirectory(currWorkingDirectory);

 var pyPlugin = PythonEngine.ImportModule(Path.GetFileNameWithoutExtension(python
 ModulePath));
 if (pyPlugin == null)
 {
      throw new PythonException();
 }

 Directory.SetCurrentDirectory(oldWorkingDirectory);

即使 test.py 文件是空的,我也会收到一个导入错误,提示“没有名为 warnings 的模块”。

'import site' failed; use -v for traceback

 Unhandled Exception: Python.Runtime.PythonException: ImportError : No module nam
 ed warnings

当你用“python -v”命令运行 test.py(详细模式)时,问题就变得明显了。你会注意到 Python 调用了 #cleanup[2] warnings。

为什么 Python .NET 不能找到 warnings 模块呢?这个模块在 Lib 目录里是存在的。

有什么想法吗?

3 个回答

2

我正在使用Python.NET的2.4版本,搭配Python 3.6,遇到了一些类似的问题。运行时设置环境变量对我来说不太顺利,但我找到了一种有效的方法。

我发现Python.NET会自动读取在静态的 PythonEngine.PythonPath 变量中定义的文件夹里的所有包。如果你的PYTHONPATH系统变量中还有其他目录,它们也会被包含进来。

如果你想在运行时包含模块目录,可以这样做:

PythonEngine.PythonPath =  PythonEngine.PythonPath + ";" + moduleDirectory;

using (Py.GIL())
{
    dynamic module = Py.Import("moduleName");
    ...etc
}

确保在调用Python引擎之前,先设置好 PythonEngine.PythonPath 变量。

另外,在调试时,如果想让系统变量的更改生效,还需要重启Visual Studio。

顺便提一下,我还发现我的 \Python36\Lib\site-packages 文件夹路径需要添加到PYTHONPATH中,这样才能找到通过pip安装的任何东西。

2

@SilentGhost 我不知道你是否解决了这个问题,但你需要设置你的 PYTHONPATH 环境变量,而不是 PYTHONHOME 变量。我之前也遇到过这个问题,使用了老办法 Environment.SetVariable("PYTHONPATH", ...) 来设置环境变量,最后一切都顺利解决了。

祝你在使用 Python.NET 时好运。

2

我觉得默认情况下,Python引擎不会自动设置你需要的路径。

http://www.voidspace.org.uk/ironpython/custom_executable.shtml 里有一个关于如何嵌入IronPython的例子。看起来你可能缺少了一些东西,比如:

PythonEngine engine = new PythonEngine();
engine.AddToPath(Path.GetDirectoryName(Application.ExecutablePath));
engine.AddToPath(MyPathToStdLib);

除非我知道IronPython安装在哪里,否则我更喜欢找到我需要的所有标准模块,把它们编译成一个IPyStdLibDLL,然后在我的代码中执行以下操作:

import clr
clr.addReference("IPyStdLib")
import site

撰写回答