#C0204
——《沧海拾昧集》@CuPhoenix
前言
在使用 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 ctypes
、from 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 中的路径分割符是/
不是\
。- 返回值用
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.Diagnostics
和System.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、运行结果
敬谢诸君。文章来源:https://www.toymoban.com/news/detail-619713.html
京华西山之巅。文章来源地址https://www.toymoban.com/news/detail-619713.html
到了这里,关于【沧海拾昧】C#调用Python代码的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!