pythonnet在.net示例中嵌入Python无法加载模块

时间:2017-11-29 18:45:19

标签: c# anaconda python-3.5 python.net python-embedding

我正在尝试从https://github.com/pythonnet/pythonnet运行.NET嵌入式Python示例。我已经按照故障排除文章将正确的%PYTHONPATH%和%PYTHONHOME%设置到程序基目录中的anaconda环境。

激活我的anaconda环境后,我已经成功导入了sys和imp作为测试,并成功使用了PythonEngine.RunSimpleString(),但numpy示例因 Python.Runtime.PythonException而失败:ImportError:No module名为'numpy'

在此环境中从python导入numpy是成功的,但是这个和其他包无法在pythonnet中导入。

Pythonnet版本:2.3 x64(使用 conda install -c pythonnet pythonnet 安装)

Python版本:Python 3.5 x64(anaconda)

操作系统:Windows 10

以下代码产生错误:

static void Main(string[] args)
{
    string envPythonHome = AppDomain.CurrentDomain.BaseDirectory + "cntk-py35";
    string envPythonLib = envPythonHome + @"\Lib";
    Environment.SetEnvironmentVariable("PYTHONHOME", envPythonHome, EnvironmentVariableTarget.Process);
    Environment.SetEnvironmentVariable("PATH", envPythonHome + ";" + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine), EnvironmentVariableTarget.Process);
    Environment.SetEnvironmentVariable("PYTHONPATH", envPythonLib, EnvironmentVariableTarget.Process);

    PythonEngine.PythonHome = envPythonHome;
    PythonEngine.PythonPath = Environment.GetEnvironmentVariable("PYTHONPATH");

    using (Py.GIL())
    {
        dynamic np = Py.Import("numpy");
        Console.WriteLine(np.cos(np.pi * 2));

        dynamic sin = np.sin;
        Console.WriteLine(sin(5));

        double c = np.cos(5) + sin(5);
        Console.WriteLine(c);

        dynamic a = np.array(new List<float> { 1, 2, 3 });
        Console.WriteLine(a.dtype);

        dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
        Console.WriteLine(b.dtype);

        Console.WriteLine(a * b);
        Console.ReadKey();
    }
}

在我的环境中,site-packages下的任何包似乎都失败了。添加到%PATH%不起作用。有没有办法让pythonnet识别并加载这些模块?

2 个答案:

答案 0 :(得分:4)

在.NET中设置python环境有点麻烦。这个问题在pythonnet网站上没有很好地解决,或者我在互联网上发现的大多数建议解决方案都不适用于我的计算机。原因是每台计算机都可能有不同的python设置环境(取决于安装python和库的方式)。我花了一段时间,但最终我成功地从.NET调用了python模块和.py脚本。这就是我所做的。

Pythonnet版本:2.4.0 x64(使用pip install @ Anaconda CMD提示符安装)

Python版本:Python 3.7 x64(Anaconda)

操作系统:Windows 10

请记住,每个人都有不同的Python环境,这就是为什么您必须首先配置环境(在VS项目中)的原因。 首先,我们需要分配“ PATH”,“ PYTHONHOME”和“ PYTHONPATH”变量。

在C#中使用:

string pythonPath1 = @"C:\Users\<your username>\Anaconda3";
        string pythonPath2 = @"C:\Users\<your username>\Anaconda3\lib\site-packages";
        Environment.SetEnvironmentVariable("PATH", pythonPath1, EnvironmentVariableTarget.Process);
        Environment.SetEnvironmentVariable("PYTHONHOME", pythonPath1, EnvironmentVariableTarget.Process);
        Environment.SetEnvironmentVariable("PYTHONPATH", pythonPath2, EnvironmentVariableTarget.Process); 

我已经使用Anaconda安装python运行时和程序包。请注意,Anaconda的默认安装位于C:\ Users(您在计算机中分配的用户名)\ Anaconda3下。 (您可以通过(How can I get the current user directory?使用代码查找您的代码。如果您没有使用Anaconda,则需要找到计算机上安装python软件包的目录。

1-C:\ Users \\ Anaconda3目录必须具有您的python DLL版本(即python37.dll)。

2-C:\ Users \\ Anaconda3 \ lib \ site-packages具有“模块”(即python框架,例如“ numpy”)。

3-您必须在项目(Python.Runtime.dll)中引用python运行时。(使用Windows File Explorer查找文件。如果使用Anaconda,则运行时位于C:\ Users \\ Anaconda3目录中。) / p>

4-在代码顶部添加以下内容:

using Python.Runtime;

5-在VS Solution Explorer中,右键单击您的项目,然后选择“属性” enter image description here

并确保设置“平台目标”(x64或x86)

6-完成所有这些操作后,如果您无法运行某些“模块”并收到“无法加载模块”或“找不到模块”异常消息,请按照此处的说明进行操作({{3 }) 通常,卸载/重新安装模块将通过更新版本来解决该问题。 (即pip卸载numpy / pip安装numpy)。

注意:即使您未在上面设置PYTHONPATH变量,该代码仍然有效。当需要调用自定义.py脚本时,可以使用PYTHONPATH变量来标识文件所在的目录。可以在https://github.com/microsoft/vscode-python/issues/9218

找到一个描述性示例

更新:我已经意识到配置Python环境的一种简单方法是使用Visual Studio(我使用VS 2017 Community版本)。只需转到https://stackoverflow.com/a/57910578/7675537并查看示例。在“ Python环境”下的VS中,您可以观察计算机中的所有设置。我在运行.py脚本时遇到问题,例如无法使用“ import matplotlib.pyplot”,并花了几个小时在互联网上阅读文章,但找不到解决方案。最后,我将环境切换到“ C:\ Users \\ AppData \ Local \ Programs \ Python \ Python37 \”,并安装了Visual Studio列表(建议)中所有缺少的软件包,并且可以正常工作。我认为从.NET(通过pythonnet或其他方式)调用Anaconda环境存在问题。如果您对python进行.NET调用,我建议不要使用Anaconda python环境。我使用:

    private static string pythonPath1 = @"C:\Users\<your name>\AppData\Local\Programs\Python\Python37";
    static void Main(string[] args)
    {
        Test();
    }

    private static void Test()
    {
        string pathToPython = pythonPath1;
        string path = pathToPython + ";" +
                      Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);
        Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
        Environment.SetEnvironmentVariable("PYTHONHOME", pathToPython, EnvironmentVariableTarget.Process);

        var lib = new[]
        {
            @"C:\Users\<your name>\<your python code is here>",
            Path.Combine(pathToPython, "Lib"),
            Path.Combine(pathToPython, "DLLs")

        };
        string paths = string.Join("; ", lib);
        Environment.SetEnvironmentVariable("PYTHONPATH", paths, EnvironmentVariableTarget.Process);

        using (Py.GIL()) //Initialize the Python engine and acquire the interpreter lock
        {
            try
            {
                // import your script into the process
                dynamic sampleModule = Py.Import("yourpythoncode");
            }
            catch (PythonException error)
            {
                Console.WriteLine("Error occured: ", error.Message);
            }

        }
    }

答案 1 :(得分:2)

我能够通过将Lib / site-packages添加到PYTHONPATH变量(而不是PATH)来导入模块,该变量将文件夹添加到sys.path。任何其他python库和自定义python代码都必须将相应的文件夹添加到PYTHONPATH。