用Python 3.7从.net调用Python脚本时出现导入错误

3 人关注

我正试图从一个.net程序中调用一个Python脚本。当我从控制台直接调用脚本时,一切正常,但当我从.net程序中调用它时,它就崩溃了,出现了以下异常。

Traceback (most recent call last):
  File "run.py", line 1, in <module>
    import pika
  File "C:\Users\USERNAME\AppData\Local\Continuum\anaconda3\envs\py37\lib\site-packages\pika\__init__.py", line 10, in <module>
    from pika.connection import ConnectionParameters
  File "C:\Users\USERNAME\AppData\Local\Continuum\anaconda3\envs\py37\lib\site-packages\pika\connection.py", line 13, in <module>
    import ssl
  File "C:\Users\USERNAME\AppData\Local\Continuum\anaconda3\envs\py37\lib\ssl.py", line 98, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: DLL load failed: The specified module could not be found.

我使用的脚本相当长,但这个错误可以通过以下简单的方法重现: 1.

import pika

(我使用的是pika 1.1.0,但pika并不是唯一出现故障的软件包,很多都是这样)。

这不是我第一次遇到这个错误了。我以前在Pycharm上遇到过,这似乎是一个常见的问题Python 3.7 anaconda环境 - import _ssl DLL加载失败错误.这种情况只发生在Python 3.7上,但很遗憾,我不能回到3.6或更低的版本。Pycharm中的修复方法是将环境变量(更确切地说,是PATH变量)明确地追加。我试着在.net中做同样的事情,但错误仍然存在。

The .net script looks something like this

using System.Diagnostics;
using System.IO;
using NLog;
using System;
namespace ConsoleApp1
    class Program
        static Logger logger = LogManager.GetCurrentClassLogger();
        static void Main(string[] args)
            string cmd = "run.py";
            ProcessStartInfo start = new ProcessStartInfo();
            start.FileName = "PATH_TO_PYTHON_3.7_ENV.exe";
            start.Arguments = string.Format("\"{0}\"", cmd);
            start.UseShellExecute = false;
            start.CreateNoWindow = true;
            start.RedirectStandardOutput = true;
            start.RedirectStandardError = true; 
            using (Process process = Process.Start(start))
                using (StreamReader reader = process.StandardOutput)
                    string stderr = process.StandardError.ReadToEnd();
                    string result = reader.ReadToEnd();
                    Console.WriteLine(stderr);
                    Console.ReadKey();

有没有人以前遇到过这个问题,并找到了解决的方法?

5 个评论
如果你还没有,试着升级到最新的Python 3.7.5版本。
Skum
我试过了,但是我使用的其他一些库还不兼容3.7.5。所以,这对我来说不是一个选择......或者说,至少在我变得非常绝望的时候才会这样做。
你现在在哪个版本上?
Skum
I'm currently on 3.7.4
AFAIK他们在3.7.2中改变了venv-script,所以如果你找不到更好的方法,回到3.7.1可能是目前的一个选择。
c#
python
.net
Skum
Skum
发布于 2019-12-03
1 个回答
amanb
amanb
发布于 2019-12-08
已采纳
0 人赞同

在我试图重现这个问题时,我发现当Python 3.6被用作env时,一切都正常,而当Python 3.7.4被用作env时,却出现了错误。在Pycharm中也观察到类似的行为(正如你指出的)。虽然根本问题可能是 Python 3.7.4 的 DLL 搜索方式,而且根本原因需要进一步调查,但我注意到当 Python 在 "非康达 "cmd 环境中被调用时,一般会出现这个错误。如果你在正常的 Windows cmd 提示下调用 Python,应该会出现以下错误(前提是 PATH 中有 "path_to_python.exe" 并且 pika 已在全系统安装)。

C:\Users\xxxxxx>python
Python 3.7.4 (default, Aug  9 2019, 18:34:13) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Warning:
This Python interpreter is in a conda environment, but the environment has
not been activated.  Libraries may fail to load.  To activate this environment
please see https://conda.io/activation
Type "help", "copyright", "credits" or "license" for more information.
>>> import pika
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\xxxxxx\Anaconda3\envs\py3.7.4\lib\site-packages\pika\__init__.py", line 10, in <module>
    from pika.connection import ConnectionParameters
  File "C:\Users\xxxxxx\Anaconda3\envs\py3.7.4\lib\site-packages\pika\connection.py", line 13, in <module>
    import ssl
  File "C:\Users\xxxxxx\Anaconda3\envs\py3.7.4\lib\ssl.py", line 98, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: DLL load failed: The specified module could not be found.

因此,当你通过C#调用Python脚本时,在Python 3.7.4中观察到类似的行为,由于conda环境没有被激活,进程在正常的cmd环境中运行,所以DLL没有被加载。

因此,在运行脚本之前激活 conda 环境应该可以解决所有版本的 Python 的这个问题。

I used the following simple Python script to test:

import pika
print("Pika imported sucessfully!")

Credits to 这个答案, 上述脚本运行成功,当我先激活conda环境时,在控制台显示了这个信息。

using System;
using System.Diagnostics;
using System.Threading;
namespace PyTest
    class Program
        static void Main(string[] args)
            string workingDirectory = @"C:\Test";
            var process = new Process
                StartInfo = new ProcessStartInfo
                    FileName = "cmd.exe",
                    RedirectStandardInput = true,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    WorkingDirectory = workingDirectory
            process.Start();
            using (var sw = process.StandardInput)
                if (sw.BaseStream.CanWrite)
                    // Batch script to activate Anaconda
                    sw.WriteLine(@"C:\Users\xxxxx\Anaconda3\Scripts\activate.bat");
                    // Activate your environment
                    sw.WriteLine("conda activate py3.7.4");                   
                    // run your script. You can also pass in arguments
                    sw.WriteLine("py pika_test.py");
            // read multiple output lines
            while (!process.StandardOutput.EndOfStream)
                var line = process.StandardOutput.ReadLine();
                Console.WriteLine(line);
                Thread.Sleep(500);

Output

Pika imported sucessfully!

要列出所有conda环境,请在Anaconda命令行中执行以下命令。

(base) C:\Users\xxxxx>conda env list
# conda environments:
base                  *  C:\Users\xxxxx\Anaconda3