如何在 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 脚本?的主要内容,如果未能解决你的问题,请参考以下文章

C#Note13:如何在C#中调用python

在.Net Framework中调用Python的脚本方法 (以VB和C#为例)

C#调用Python的最优方式

在C#环境中动态调用IronPython脚本

Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween

可以调用无限运行的 Python 脚本的 Windows 服务(在 C# 中)?