如何在 c# 中调用 python 脚本?
Posted
技术标签:
【中文标题】如何在 c# 中调用 python 脚本?【英文标题】:How can I call python script in c#? 【发布时间】:2021-07-23 00:19:25 【问题描述】:我正在开发一个需要在 c# 中调用 python 脚本的项目。事实是我熟悉python,但不熟悉c#,一点也不熟悉。
据我所知,基本上有两种选择:Iron 和 Python.net,您可以在这里查看 https://www.youtube.com/watch?v=oG5mmElsWJM&lc=UgzwcXvIteCqTjmHl2N4AaABAg.9Ls9q7VkDdc9MCYIPfOW0d。我现在在 python.net 上苦苦挣扎。我试图调用一个简单的乘法函数(例如 a * b),效果很好。但是当我转向图像数据时,弹出一个名为“'Delegates'的类型初始化程序引发异常。”的错误。
我使用的python脚本是:
import cv2
import numpy as np
def binarise(image):
ret, img_output = cv2.threshold(image,100,255,cv2.THRESH_BINARY)
return img_output
我试过的c#是:
if (greyImage1 != null)
try
var pythonPath = @"C:\Users\Admin\anaconda3";
Environment.SetEnvironmentVariable("PATH", $@"pythonPath;" + Environment.GetEnvironmentVariable("PATH"));
Environment.SetEnvironmentVariable("PYTHONHOME", pythonPath);
Environment.SetEnvironmentVariable("PYTHONPATH ", $@"pythonPath\Lib");
string scriptFile = "myfunction.py";
string pythonCode = "";
using (var streamReader = new StreamReader(scriptFile, Encoding.UTF8))
pythonCode = streamReader.ReadToEnd();
using (Py.GIL())
var scope = Py.CreateScope();
scope.Exec(pythonCode);
greyImage1 = (scope as dynamic).binarise(greyImage1);
pictureBox1.Image = (System.Drawing.Image)greyImage1;
this.Cursor = Cursors.Default;
catch (Exception ex) messageL.Text = ex.Message;
有人有什么想法吗?感谢您的时间和帮助。
【问题讨论】:
看看这里:***.com/questions/10257000/… 这里的 grayImage1 是什么?将 .net 对象传递给 pythonnet 时,您需要调用 ToPython() 因此您需要执行 grayImage1.ToPython() 但这仍然行不通,因为您需要将图像数据类型更改为 opencv 期望的,即输入输入数组 谢谢。 grayImage1 处于浮动状态,我尝试在 python 脚本中将其更改为 2d 数组,以便我可以将 grayImage1 直接传递给函数。但没有运气。您认为这是什么原因? 谢谢roboto1986。我可以更改 python 脚本中的数据类型以使其可被 opencv 识别。我还将 grayImage1 替换为 grayImage1.ToPython()。我相信现在可以将数据发送到python,我现在的问题是在python函数之后,数据如何存储并返回到c#,以确保它可以被c#识别? 似乎在python之后,它作为pyobject返回,因为我收到错误[无法将类型'Python.Runtime.PyObject'隐式转换为'System.Drawing.Bitmap']。那么如何使用正确的数据类型回到 c# 呢? 【参考方案1】:这里的主要思想是使用新初始化的进程调用脚本并获取其标准输出。此方法需要外部 Python 解释器来实际执行脚本
public string run_cmd(string cmd, string args)
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "PATH_TO_PYTHON_EXE";
start.Arguments = string.Format("\"0\" \"1\"", cmd, args);
start.UseShellExecute = false;// Do not use OS shell
start.CreateNoWindow = true; // We don't need new window
start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
using (Process process = Process.Start(start))
using (StreamReader reader = process.StandardOutput)
string stderr = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
string result = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
return result;
您可以传递您的命令和参数,这些命令和参数将由 Python exe 的给定路径执行。
记住,当您运行此类代码时,您需要考虑运行主应用程序的帐户的权限。例如,如果您想从托管在 IIS 上的 Web 服务运行脚本,请确保所有需要执行的脚本文件都对运行您的 Web 服务ApplicationPool
的用户具有正确的权限.
请参阅此LINK 了解更多详情。
【讨论】:
【参考方案2】:[更新] 我很确定问题发生在这一行: grayImage1 = (scope as dynamic).binarise(greyImage1); 这实际上转向了数据类型转换。 python 脚本的输入和输出数据是 uint8 的二维数组,但我不确定 c# 期望或返回什么数据类型。
[更新] 数据通信问题已解决。 c#的结果只是数字,发送给python的时候,我们需要先把它做成一个list,然后做成二维数组,再转成uint8,这样opencv才能识别。 python的结果可以直接返回给c#。但是记住它是 PyObject,所以需要把它改成字符串,然后做任何你想做的事情。
【讨论】:
以上是关于如何在 c# 中调用 python 脚本?的主要内容,如果未能解决你的问题,请参考以下文章
在.Net Framework中调用Python的脚本方法 (以VB和C#为例)