【沧海拾昧】C#调用Python代码的方法

#C0204

沧海茫茫千钟粟,且拾吾昧一微尘

——《沧海拾昧集》@CuPhoenix

【阅前敬告】
沧海拾昧集仅做个人学习笔记之用,所述内容不专业不严谨不成体系
【如有问题必是本集记录有谬,切勿深究】

目录

  • 前言
  • 一、测试环境准备
  • 二、实现过程
    • 1、准备 .py 文件
    • 2、C# 实现
    • 3、运行结果

前言

  在使用 C# 调用 Python 代码时,有多种方法,如将Python封装为动态链接库 .dll 、用 IronPython 作为移植的依赖库直接调用 Python 的函数接口等,但在开发时最简单实用的方法莫过于利用 C# 命令行调用 .py 文件执行

  本文记录了在利用 C# 命令行调用 .py 文件执行的方法与可能遇到的常见问题。

一、测试环境准备

  为演示如何 C# 命令行调用 .py 文件执行,本例的实现功能与准备如下:

实现功能:

  • 单击 C# 窗口中的 button1,调用 .py 文件执行一个简单的加法,并将值传回给窗口,显示在 button1.Text 上。

软件版本:

  • Python 3.6.2 (x86)
  • Visual Studio 2019

二、实现过程

1、准备 .py 文件

  准备一段功能简单的 Python 代码作为样例测试所用。代码如下:

#main.py

import sys
import ctypes
from ctypes import *

def func(a,b):
    mydll = CDLL("F:/xxxxx/TestDll.dll")    # 强烈建议使用绝对路径
    result = mydll.add(a, b)
    return result

if __name__=='__main__':
    try:
        #代码行
        a = int(sys.argv[1])
        b = int(sys.argv[2])
        c = func(a,b)
    except Exception as err:
        #捕捉异常
        str1 = 'default:' + str(err)
    else:
        # 代码运行正常
        str1 = c
    print(str1)

代码说明:

  • 代码中使用的import ctypesfrom ctypes import *mydll = CDLL("xxxx")这一部分用于引入一个自编的 .dll 库,这个库里一个 add 函数用以执行两个整型数相加,这个库是通过 C++ 实现的,实现了 Python 中调用 C++ 代码,详情可参见《》。
  • 在测试时,可删去上述三行,并改写result = mydll.add(a, b),为 result 赋值。
  • mydll = CDLL("F:/Test/Debug/Test Dll1.dll") 强烈建议使用绝对路径,注意 Python 中的路径分割符是 / 不是 \
  • 返回值用 print 直接输出即可。

2、C# 实现

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;	// 必须引入
using System.Drawing;
using System.IO;	// 必须引入
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Project1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
		// 单击按钮触发测试
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                string path = @"F:\xxxxx\main.py";  // 所需调用的 .py 文件的绝对路径
                StartTest(path, 1, 2);
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message);
            }
        }
        
        //调用python核心代码
        private Process progressTest;
        public bool StartTest(string pathAlg, int a, int b)
        {
            bool state = true;

            if (!File.Exists(pathAlg))
            {
                throw new Exception("The file was not found.");
            }
            string sArguments = @"""" + pathAlg + @"""";  // 进一步处理路径。在路径前后加上双引号。
            sArguments += " " + a.ToString() + " " + b.ToString() + " -u";	 // 加上传入的参数

            ProcessStartInfo start = new ProcessStartInfo();
            start.FileName = @"python.exe";  // 需事先配置好环境路径,否则必须使用绝对路径
            start.Arguments = sArguments;
            start.UseShellExecute = false;
            start.RedirectStandardOutput = true;
            start.RedirectStandardInput = true;
            start.RedirectStandardError = true;
            start.CreateNoWindow = true;

            progressTest = Process.Start(start);
            // 为异步获取订阅事件
            progressTest.OutputDataReceived += new DataReceivedEventHandler(outputDataReceived);
            // 异步获取命令行内容
            progressTest.BeginOutputReadLine();
            progressTest.BeginErrorReadLine();
            
            return state;
        }

        public void outputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                this.Invoke(new Action(() => {
                    this.button1.Text = e.Data;  // e.Data中是 .py 执行完传回的值
                }));
            }
        }
    }
}

代码说明:

  • 程序中使用到了文件的读取和 Process 类,因此必须引入System.DiagnosticsSystem.IO
  • string sArguments = @"""" + pathAlg + @""""; 一步,用于为路径前后加上双引号,否则在控制台执行命令时,无法正确处理路径中的空格,导致调用失败。@ 是 C# 中的字符串的转义符,“”用于转义出一个双引号。即:@"""" 是只含有一个双引号的 string 。
  • ProcessStartInfo.sArguments 中是用以执行的命令行,其在 cmd 中的形式是 python "绝对路径/xxxx.py" a b ,其中 a 、 b 是向 .py 文件中传入的参数。在 C# 中使用,仅需将ProcessStartInfo.FileName 的值设为 @"python" (需要事先配置好 Python 的环境参数,否则必须使用绝对路径),然后将ProcessStartInfo.sArguments的值设为"绝对路径/xxxx.py" a b 即可。
  • OutputDataReceived 事件中传入的 DataReceivedEventArgs e.Data 中记录了 .py 输出到控制台命令行的值。

3、运行结果

运行结果,成功调用 .py 中的代码

敬谢诸君。

京华西山之巅。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年8月17日
下一篇 2023年8月17日

相关推荐