C#與Python互動方式

chaney1992發表於2021-04-18

前言:

 在平時工作中,需求有多種實現方式;根據不同的需求可以採用不同的程式語言來實現。發揮各種語言的強項

 如:Python的強項是:資料分析、人工智慧等

   .NET 開發桌面程式介面比Python更簡單、方便、美觀

 那麼就存在各種語言間互動,本篇主要介紹幾種C# 與 Python的互動方式。

一、IronPython

 1、IronPython是什麼?  

IronPython是Python程式語言的開源實現,該語言與.NET Framework緊密整合。IronPython可以使用.NET Framework和Python庫,而其他.NET語言也可以輕鬆使用Python程式碼。

 2、IrconPython如何使用

  a) 新增包引用:

Install-Package IronPython -Version 2.7.11

  b) 執行簡單python指令碼:   

//建立執行引擎
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
string script = "'Hello %d' %number";
//設定引數列表
scope.SetVariable("number", 123);
ScriptSource sourceCode = engine.CreateScriptSourceFromString(script);
var result = sourceCode.Execute<object>(scope);

  c) 執行python檔案方法:

   新增如下簡單Python檔案:demo.py

#檔案目錄 demo.py
import time

def welcome(name):
    return "hello " + name

def Add(a, b):
    return a + b

def showMsg(name,birthday):
    return "姓名:" + name + ",生日:" + birthday

   執行方法:

string path = @"demo.py";
ScriptRuntime pyRuntime = Python.CreateRuntime(); //建立一下執行環境
dynamic obj = pyRuntime.UseFile(path);
//呼叫python中Add函式
object sum = obj.Add(1, 54);

  d) 執行python檔案方法(依賴三方庫):

from scipy import linalg
import numpy as np
import json

def calcnum(jsonInput):
    A = np.array([[1, 1, 7], [2, 3, 5], [4, 2, 6]])  # A代表係數矩陣
    b = np.array([2, 3, 4])  # b代表常數列
    x = linalg.solve(A, b)
    # json字串轉物件
    info = json.loads(jsonInput)
    print(info['a'])
    # 物件轉json字串
    output = json.dumps(info)
    print(output)
    print(x) 

    執行結果:    

    

  IronPython雖然能夠互動Python,但支援的庫不多,當py檔案依賴三方庫,則會呼叫失敗;且IronPython對Python3尚未完全支援,下面就開始在C#在Python有第三方庫的情況下互動Python。  

二、Python打包exe呼叫

 把Python打包成exe,C#再通過cmd進行互動。就可以解決第三方庫的問題;

 修改Python檔案(calc.py):依賴了scipy庫

from scipy import linalg
import numpy as np
import json

def calcnum(jsonInput):
    A = np.array([[1, 1, 7], [2, 3, 5], [4, 2, 6]])  # A代表係數矩陣
    b = np.array([2, 3, 4])  # b代表常數列
    x = linalg.solve(A, b)
    # json字串轉物件
    info = json.loads(jsonInput)
    print(info['a'])
    # 物件轉json字串
    output = json.dumps(info)
    print(output)
    print(x)


if __name__ == '__main__':
    inputString = sys.argv[1]
    calcnum(inputString)

 Pyinstaller:

PyInstaller 是一個程式,將(包)Python 程式打包到獨立的可執行檔案中,在 Windows、Linux、Mac OS X、FreeBSD、Solaris 和 AIX 下。與類似工具不同,它的主要優點是 PyInstaller 可以與 Python 2.7 和 3.3_3.5 配合使用,它通過透明壓縮構建更小的可執行檔案,它是完全多平臺的,並使用作業系統支援來載入動態庫,從而確保完整相容性。
PyInstaller 的主要目標是與開箱即用的第三方軟體包相容。這意味著,使用 PyInstaller 時,所有使外部包正常工作所需的技巧都已整合到 PyInstaller 本身中,因此無需使用者干預。您永遠不需要在 wiki 中查詢技巧,並將自定義修改應用於檔案或設定指令碼。例如,像PyQt、Django或matplotlib這樣的庫完全支援,而無需手動處理外掛或外部資料檔案。 

  安裝:

  在Cmd命令列中執行:需提前安裝pip(python3.4以後預設包含)

pip install pyinstaller

  打包:   

//命令格式
pyinstaller 選項 Python 原始檔

   選項引數支援以下內容:    

引數描述
-H, -help 檢視幫助文件
-F,-onefile 產生單個的可執行檔案
-D,--onedir 產生一個目錄(包含多個檔案)作為可執行程式
-a,--ascii 不包含 Unicode 字符集支援
-d,--debug 產生 debug 版本的可執行檔案
-w,--windowed,--noconsolc 指定程式執行時不顯示命令列視窗(僅對 Windows 有效)
-c,--nowindowed,--console 指定使用命令列視窗執行程式(僅對 Windows 有效)
-o DIR,--out=DIR 指定 spec 檔案的生成目錄。如果沒有指定,則預設使用當前目錄來生成 spec 檔案
-p DIR,--path=DIR 設定 Python 匯入模組的路徑(和設定 PYTHONPATH 環境變數的作用相似)。也可使用路徑分隔符(Windows 使用分號,Linux 使用冒號)來分隔多個路徑
-n NAME,--name=NAME 指定專案(產生的 spec)名字。如果省略該選項,那麼第一個指令碼的主檔名將作為 spec 的名字

   最後在命令列中執行命令:

    pyinstaller -F calc.py

   打包完成後,生成calc.exe檔案:

   

   呼叫:

private string Calc(string inputString)
{
    // 呼叫python指令碼
    Process p = new Process();
    p.StartInfo.FileName = "calc.exe";
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.CreateNoWindow = true;
    // 注意,這前面得有一個空格,不然就連在一起了
    p.StartInfo.Arguments = " " + inputString;
    p.Start();
    string output = p.StandardOutput.ReadToEnd();
    p.WaitForExit();
    p.Close();
  return output; }

 到此該方法已能成功呼叫Python結果 

三、Python提供WebApi介面(推薦)

 使用Python中flask庫實現一個簡單的webapi服務:

from flask import Flask, request
import Math
app = Flask(__name__)

@app.route("/")
def welcome():
    return "Hello World!"

@app.route("/calc")
def calc():
    strinput = request.args.get("jsonInput")
    return Math.calcnum(strinput)

if __name__ == "__main__":
    app.run()

 最後在C#中呼叫webapi:得到python結果

  

總結:

 通過以上內容知道各種語言平臺想互動,雖然有多種方式實現;但是最為推薦還是提供Webapi介面方式。

 

相關文章