【问题标题】:Executing Python Script from Windows Forms .NET从 Windows Forms .NET 执行 Python 脚本
【发布时间】:2022-02-24 22:07:32
【问题描述】:

总的来说,我对 Python 和 .NET 还很陌生,但我决定问问更有能力的人,因为我一直在努力解决从 Windows 窗体执行 python 脚本的问题。

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

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

我尝试过使用 IronPython,它运行良好,直到我发现 Iron Python 不支持 CPython 包,比如 Pandas,它是基于 numpy 构建的,而 numpy 显然是其中之一。我查看了很多关于这个问题的文章,答案似乎并不乐观,大多数建议都是使用 pythonnet。

我尝试实现pythonnet,遵循了许多文章,而我所做的一切,除了造成更大的混乱之外,什么都没有。

最后,我决定使用 C# Process 类,但也没有成功。

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

Python version: 3.7

Windows 10 (64 bit)

.NET Framework 4.7.2

这是我在 Windows 窗体中的一些代码尝试:

使用流程类实现

这里的问题是我无法运行这个脚本,因为它无法找到 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, Version=2.5.2.0, Culture=neutral....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 脚本,并得到了 no module found 错误

我知道这些不是最好的实现,但要做好。

我的问题是,如果有人对如何使这个简单的操作工作有任何想法,我将非常感激,感谢您的时间和理解

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

【问题讨论】:

  • 您似乎希望脚本在 python 3.x 中运行,但您为 ProcessStartInfo 提供的路径适用于 python 2.7 版。也许通过版本 3.x 的路径,然后重试。
  • @yohannist 我提供的 ProcessStart 脚本将基本解释器设置为 python 2.7。但是无论如何尝试使用 3.x 运行它并没有工作。

标签: python c# .net ironpython python.net


【解决方案1】:

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

  1. 确认在您的环境变量(WIN+R、sysdm.cpl、高级、环境变量)中设置的 python 实例是您希望使用的 python 实例(也为您的 python 搜索路径执行此操作!)

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

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

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

Process.Start(processStartInfo);

【讨论】:

  • 嗨,Shawn,该项目专门与网页抓取有关,我在脚本文件中有几个库。执行 Process.Start() 后,我收到以下错误 bs4 import BeautifulSoup ImportError: No module named bs4
  • 我已经导入了 urllib、BeautifulSoup、sys 和 pandas。但是它不能从第二次导入中识别出来,我相信因为我必须以某种方式告诉 Process 在所有这些包所在的特定路径中查找,以便它可以与脚本一起运行它们。这个我不知道该怎么做。
  • 你在使用的python实例中安装了Beautiful soup吗? CMD提示:python,导入bs4?也许它被安装在另一个安装中。或者...未配置 env var 中的 pythonpath。
  • 不应该告诉进程信息...使用环境变量的好处在于它将所有配置排除在您的 C# 代码之外。
  • 是的,包在这个项目的正确位置,它们位于 site-packages 文件夹中。我添加了几个环境。变量不仅适用于 python 2.7,而且适用于 python 2.7 文件夹中的项目、脚本和 Lib 文件夹的相应包位置,但仍然会出现找不到模块的错误。
【解决方案2】:

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

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

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

经过进一步调查,我发现我的脚本包被视为“本地”包,这意味着我从 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="$1"

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

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

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

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

有用的文章:

Installed BeautifulSoup but still get no module named bs4

Passing arguments to Python from Shell Script

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

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

感谢所有做出贡献并试图提供帮助的人,我设法通过您的建议学到了新东西!

【讨论】:

    猜你喜欢
    • 2017-05-29
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 2015-10-26
    相关资源
    最近更新 更多