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