The interaction between c# and Python perfectly solves the problem of Python calling OpenCV and other third-party libraries and configuring the python environment when distributing

Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right


foreword

Regarding how C# calls Python, there are many solutions on the Internet, such as ironPython, some that package python code into exe, and some that call python through the process class, but these solutions have more or less defects, such as ironPython cannot Calling third-party libraries, packaged into exe, running too slow, etc. This article mainly proposes a solution to the problem of installing the python environment when the Process class calls python and distributes it to others.


提示:以下是本篇文章正文内容,下面案例可供参考

1. Problem analysis

How C# calls Python, there is a very classic solution, which is to use the Process class of C# to create a process. This process is actually developed for the Python interpreter. Through this process, the Python code can be perfectly called. The principle of this solution is actually equivalent to using a python interpreter to execute a piece of python code yourself, except that the process of "using the Python interpreter" is not executed manually, but is automatically executed by C# through the process class. See the key code below

            Process P = new Process();
            //当前debug目录路径
            string curPath = System.Environment.CurrentDirectory;
            //需要调用的python代码文件
            string path =  curPath + "\\" + sArgName;
            //python解释器的路径
            P.StartInfo.FileName = curPath + "\\" + "python3\\python.exe";
            //传递的参数,注意,参数数组从0开始索引,第0个参数永远是python代码路径
            //从第一个参数开始是函数的形参
            string sArguments = path;

There are two problems here:
first, when a third-party library is called in python code, how does the python interpreter know where to find the location of the third-party library.
Second, when distributing to a user who has not installed Python, how can the user be prevented from downloading Python, but can be used directly.

Two, the solution

first question

If the third library is referenced in the Python code, the Python interpreter will look for the corresponding library from its sibling directories, environment variables, and manually added directories. We can understand this from the python installation directory. The following figure is the author's python installation directory.
insert image description here
When you call Python.exe, it will search for the corresponding site-packages folder in the LIB folder in the same level directory. If the third-party library is found, it will run successfully, otherwise it will report an error.

second question

When distributing to users, if the user does not have a python environment installed, the code that can run on your computer will report an error because the corresponding module cannot be found on the user's side. The general solution is to install a python environment for users, but this will undoubtedly affect the user experience. The best solution is to configure the python environment in the distributed project files.
Inspired by the first question, the python interpreter will look for third-party libraries and other dependent files in the same directory, then we can create a new python folder in the project file, and then configure the python environment in it. The specific operation is very simple, just copy all the contents of the folder where the python interpreter is installed. Of course, in this case, the folder may be very large, which is generally because there are many third-party libraries in site-packages. You only need to keep the relevant libraries in site-packages when copying, and delete all other irrelevant ones to reduce the space. For example, in the author's demo, c# needs to call python's opencv to display pictures, so opencv needs to be kept in site-packages and numpy library will do. See below
insert image description here
insert image description here
insert image description here

3. Results and source code

 private void button2_Click(object sender, EventArgs e)
        {
    
    
            //打开图片文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "请选择图片文件";
            ofd.InitialDirectory = @"C:\Users\17116\Desktop";
            ofd.Filter = "图片文件|*.*";
            ofd.ShowDialog();
            url = ofd.FileName;
            string[] strArr = new string[2];//参数列表
            string sArgName = "main.py";//调用的.py文件名
            //strArr[0] = textBox1.Text;
            //strArr[1] = textBox2.Text;
            strArr[0] = url;
            RunpythonScript(sArgName, strArr);//运行python
        }

        public static void RunpythonScript(string sArgName, params string[] teps)
        {
    
    
            Process P = new Process();
            //当前debug目录路径
            string curPath = System.Environment.CurrentDirectory;
            //需要调用的python代码文件
            string path =  curPath + "\\" + sArgName;
            //python解释器的路径
            P.StartInfo.FileName = curPath + "\\" + "python3\\python.exe";
            //传递的参数,注意,参数数组从0开始索引,第0个参数永远是python代码路径
            //从第一个参数开始是函数的形参
            string sArguments = path;
            foreach (string sigter in teps)
            {
    
    
                sArguments += " " + sigter;//传递参数,两次之后为 路径 参数一 参数二
            }
            P.StartInfo.Arguments = sArguments;//启动python需要的命令语句
            P.StartInfo.UseShellExecute = false;
            P.StartInfo.RedirectStandardOutput = true;
            P.StartInfo.RedirectStandardInput = true;
            P.StartInfo.RedirectStandardError = true;
            P.StartInfo.CreateNoWindow = true;
            P.Start();
            P.BeginOutputReadLine();//在应用程序的output流上异步读取数据
            P.OutputDataReceived += new DataReceivedEventHandler(P_OutputDataReceived);//事件触发器,有新的数据就读取
            P.WaitForExit();
        }
        //用于C#和python之间字符串类型数据的传递
        static void P_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
    
    
            //if (!string.IsNullOrEmpty(e.Data))//如果字符串存在
            //{
    
    
            //    MessageBox.Show(Convert.ToString(e.Data));//显示结果
            //}

        }

python code in main.py

import cv2
import sys

def add(a,b):
    return (float(a) + float(b))

def imgshow(path):
    img = cv2.imread(path)
    cv2.imshow("img",img)
    cv2.waitKey()

imgshow(sys.argv[1])
# print(add(sys.argv[1],sys.argv[2]))

# if __name__ == '__main__':
#     print(add(sys.argv[1],sys.argv[2]))

Click the select picture button in the figure, c# will call the main.py file, and display the picture through opencv
insert image description here
insert image description here

Four. Summary

This article calls python through the process class, you can use python's third-party library, and you don't need to install the python environment when distributing to users. But there is still a shortcoming: the problem of data transmission of non-string types such as pictures. These are two different processes. How to load the picture data processed by python directly into the memory of c#, instead of reading the file (this will be very slow), is the follow-up improvement direction.
Finally, I will list a few ideas for calling python from C# that have not been tested:
1. Use the Python.NET library: Python.NET is a library for running Python code on the .NET platform. It provides a link between C# and Python. Interface. You can use the Python.NET library to call Python code from a C# program.

2. Use Pyjion: Pyjion is an open source JIT compiler that can compile Python code into .NET machine code. You can use Pyjion to call compiled Python code from a C# program.
PS If you need the complete code, you can download it from this link. Bloggers also need some credits to download resources. Those who are interested hope to give more support. Complete code download

Guess you like

Origin blog.csdn.net/bookshu6/article/details/128283187