从 Windows Forms .NET 执行 Python 脚本

Executing Python Script from Windows Forms .NET

总的来说,我对 Python 和 .NET 还比较陌生,但我决定请教更有能力的人,因为我一直在努力解决从 [=79= 执行 python 脚本的问题] 表格。

我的项目的基本思想是一个桌面应用程序,整体逻辑是从几个选中的复选框中读取,将这些选择的值传递到我的 python 脚本,从那里我生成基于这些结果的 excell table,并将此 table 显示回 Windows Forms 应用程序。

创建 table 并设法在桌面应用程序中显示它已经完成,但我在执行脚本本身时遇到了两个平台之间的通信的严重问题。

我已经尝试使用 IronPython 并且它工作得很好,直到我发现 Iron Python 不支持 CPython 包,比如 Pandas ,它建立在 numpy 之上,而 numpy 显然是其中之一。我看了很多关于这个问题的文章,答案似乎不太乐观,大多数建议都是使用 pythonnet.

我尝试实施 pythonnet,阅读了大量文章,但我所做的一切除了造成更大的混乱之外,结果什么也没有。

最后,我决定使用C#进程class,但也没有成功。

如果有任何关于如何解决此问题的意见和建议,我们将不胜感激。

Python version: 3.7

Windows 10 (64 bit)

.NET Framework 4.7.2

这是我在 Windows 表单中的一些代码尝试:

使用流程实现Class

这里的问题是我无法 运行 这个脚本,因为它找不到 python 脚本

的包的错误消息
var processStartInfo = new ProcessStartInfo
{
    Arguments = "C:\Users\Dobromir\PycharmProjects\pythonProject\main.py",
    FileName = "C:\Python27\python.exe",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    CreateNoWindow = true
};

Process.Start(processStartInfo);

使用 IronPython 实现(在使用 pandas 包之前有效)

这里的问题是 CPython 包的限制和错误。

对于 IronPython 我必须降级到 Python 2.7 才能使用它。对于其余示例,我使用 Python 3.7

ScriptEngine pythonEngine = Python.CreateEngine();
var searchPaths = pythonEngine.GetSearchPaths();

searchPaths.Add(@"C:\Python27\Lib");
searchPaths.Add(@"C:\Users\Dobromir\PycharmProjects\pythonProject\venv\Lib\site-packages");

pythonEngine.SetSearchPaths(searchPaths);

List<String> argv = new List<String>();

argv.Add("Some Value1");
argv.Add("Some Value2");

ScriptSource pythonScript = pythonEngine.CreateScriptSourceFromFile("C:\Users\Dobromir\PycharmProjects\pythonProject\main.py");

pythonEngine.GetSysModule().SetVariable("argv", argv);
pythonEngine.SetSearchPaths(searchPaths);

ScriptScope scope = pythonEngine.CreateScope();

pythonScript.Execute(scope);

pythonnet的实现 我这里得到的问题是使用 Py.GIL() 在线。我相信它在查找 python 文件时遇到问题,并且还尝试在变量 pathToPython.

中给出 python37.dll

我收到错误 Python.Runtime,版本=2.5.2.0,文化=中性....missmatch

string pathToPython = @"C:\Users\Dobromir\AppData\Local\Programs\Python\Python37";
string path = pathToPython + "; " + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);

Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToPython, EnvironmentVariableTarget.Process);

Console.WriteLine(path);

var lib = new[]
{
  @"C:\Users\Dobromir\PycharmProjects\App37\main.py",
  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
  {
     Console.WriteLine("I am working");
  }
  catch (PythonException error)
  {
   Console.WriteLine("Error occured: ", error.Message);
  }
}

我还尝试创建一个 bash 脚本来执行 python 脚本,但也遇到了找不到模块的错误

我知道这些并不是目前最好的实现方式,但请完成工作。

我的问题是,如果有人知道如何使这个简单的操作起作用,我将不胜感激,感谢您的时间和理解

P.S - 很抱歉post,想写下我在寻求帮助之前尝试过的内容,但如果有人更感兴趣,我会提供更多信息。

我最近做了一个这样的项目;我建议一些事情让它变得简单:

  1. 确认你的env变量(WIN+R,sysdm.cpl,Advanced,env variables)中设置的python的实例是[=26的实例=] 您希望使用(也为您的 python 搜索路径执行此操作!)

  2. 删除任何试图在代码中设置这些的行;如果找不到则处理错误

然后,当您从程序中调用脚本时;它只需要看起来像这样:

var processStartInfo = new ProcessStartInfo
{
    Arguments = "main.py",
    FileName = "Python",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    CreateNoWindow = true
};

Process.Start(processStartInfo);

经过一番努力,我找到了满足我需求的解决方案。

首先,我完全删除了 python 2.7 并重新安装了 3.10。

我在 shell 命令行中尝试了 运行 脚本文件,但得到了同样的错误,即找不到模块。我所做的是尝试导入这些模块,但它给出了一个错误,特别是对于 bs4,我正在使用 python 2.x 的包而不是 3.x 包。

经过进一步调查,我发现我的脚本所用的包被视为“本地”包,这意味着我从 IDE (PyCharm) 安装了它们,并且它们为此工作我猜只是项目。

我还发现,要“全局”访问这些包,我必须使用 pip3 install 通过命令行安装它们。这样做之后,问题就消失了,剩下 运行 来自 Windows 表单的脚本。

注意:我没有设法使用 python.exe 启动脚本,所以我使用 bash 脚本来完成作业。

这是我的代码,我希望它能帮助下线的人...

C# 代码

string myApp = string.Format("{0} {1}", @"C:\testing1.sh", "Hello");

var processStartInfo = new ProcessStartInfo
{
  Arguments = myApp,
  FileName = "C:\Program Files\Git\git-bash.exe",
  UseShellExecute = false,
  RedirectStandardOutput = true,
  CreateNoWindow = false
};

Process.Start(processStartInfo)

Bash 脚本文件中的代码

#!/bin/bash

arg1=""

python C:/Users/Dobromir/PycharmProjects/testing/main.py "$arg1"

在 Python 文件中,我正在使用 sys.argv[] 并访问参数。

注意: 将参数从 bash 脚本传递到 python 脚本,在这种情况下,您将收到 2 参数 - 第一个是 python 文件的路径,第二个是变量 arg1.

另一个需要提及的重要事项是您需要在 $1 周围加上逗号 - 这是从 C# 文件发送的 属性,否则它将显示为空。

有用的文章:

https://unix.stackexchange.com/questions/31414/how-can-i-pass-a-command-line-argument-into-a-shell-script

https://gist.github.com/creativcoder/6df4d349447ff1416e68

感谢所有做出贡献并试图提供帮助的人,我在你们的建议下学到了新东西!