C#调用python脚本
由于项目的上位机(采用C#编写的winform程序)需要使用数据拟合等功能,而python作为数据处理方面优秀的工具,众多的第三方库使得处理数据得心应手。于是考虑采用C#+Python混合编程的方式来实现上位机的相关功能。
通过查阅资料发现,C#调用python脚本主要有两种方式:
-
一是使用IronPython这个工具,但不巧的是目前只支持python2,IronPython3在GitHub上的公告显示还在开发中,遂放弃(费了好大的劲,才搞明白)。
-
另一种方式就是有C#程序使用Cmd命令行来调用Python脚本。在实际使用中发现无论是通过命令行由C#向python程序传参,还是C#截取python的运行结果都存在数据转换麻烦的困难。遂想通过统一的接口来实现,而操作系统中文件是相对统一的东西,于是考虑采用文件传参的方式来实现功能。
实现思路如下:
类似于嵌入式中的通道通信,通过打开的文件进行数据交换。
C#程序部分:
将参数写入文件的函数
private static bool saveToCSVFile(double[] x_value, double[] y_value)
{
bool successwriteFlag = true;
List<double> X = new List<double>(x_value);
List<double> Y = new List<double>(y_value);
StringBuilder strValue = new StringBuilder();
StreamWriter fs = new StreamWriter(@"DataToPython.csv");
try
{
for (int i = 0; i < X.Count; i++)
{
strValue.Append(X[i].ToString());
if (i < X.Count - 1)
{
strValue.Append(",");
}
else
{
strValue.Append("\n");
}
}
for (int i = 0; i < Y.Count; i++)
{
strValue.Append(Y[i].ToString());
if (i < Y.Count - 1)
{
strValue.Append(",");
}
else
{
strValue.Append("\n");
}
}
fs.Write(strValue);
}
catch (Exception ex)
{
successwriteFlag = false;
}
finally
{
fs.Dispose();
}
return successwriteFlag;
}
通过命令行启动Python脚本的函数
private static bool runPythonCmd()
{
bool successRunPythonFlag = true;
var p = new Process();
try
{
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系统Shell启动
p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的接收信息
p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true; //重定向标准错误输出
p.StartInfo.CreateNoWindow = true; //不显示cmd命令行窗口
p.Start();
p.StandardInput.WriteLine("python curvefitting.py"); //启动python脚本
p.StandardInput.WriteLine("exit");
p.StandardInput.AutoFlush = true;
p.WaitForExit(); //等待程序执行完退出进程
}
catch(Exception ex)
{
successRunPythonFlag = false;
}
finally
{
p.Close();
}
return successRunPythonFlag;
}
Python程序部分:
import numpy as np
import csv
# 读取csv文件
csv_data = csv.reader(open('DataToPython.csv', encoding='utf-8'))
x = []
y = []
# 按行分为x,y数据
for i, row in enumerate(csv_data):
if i == 0:
x = list(map(int, row))
if i == 1:
y = list(map(int, row))
x = np.array(x)
y = np.array(y)
f = np.polyfit(x, y, 3) # 拟合函数
fittingvalues = np.polyval(f, x) # 拟合值
print(f)
p = np.poly1d(f)
print(p)
print(fittingvalues)
np.savetxt("Result.csv", f.reshape(1, -1), delimiter=',')
在C#主函数中调用代码即可:
static void Main(string[] args)
{
double[] x = { 1, 2, 3, 6, 8 };
double[] y = { 10, 11, 13, 19, 20 };
bool successwriteFlag = saveToCSVFile(x, y);
if(successwriteFlag)
{
bool successRunPythonFlag = runPythonCmd();
if(successRunPythonFlag)
{
Console.WriteLine("运行python脚本成功");
}
else
{
Console.WriteLine("运行python脚本失败");
}
}
else
{
Console.WriteLine("写入csv文件失败");
}
}
END