C#/.net程序調(diào)用Python的教程分享
C#/.net程序調(diào)用python
C#的優(yōu)勢在于window下的開發(fā),不僅功能強(qiáng)大而且開發(fā)周期短。而python則有眾多的第三方庫,可以避免自己造輪子,利用C#來做界面,而具體實(shí)現(xiàn)使用python來實(shí)現(xiàn)可以大大提高開發(fā)效率。本文介紹如何使用pythonnet來執(zhí)行python腳本,使用pythonnet既可以具有較高的交互性,又可以使用第三方python庫,同時(shí)可以將程序需要的python環(huán)境及第三方庫打包到軟件中,避免用戶進(jìn)行python的環(huán)境配置。
C#調(diào)用python的常見方法
調(diào)用python常見的方法有4種
| 方式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|
| 使用IronPython | 無需安裝python運(yùn)行環(huán)境,交互性強(qiáng),C#和python無縫連接 | 某些python第三方庫不支持,如numpy |
| 使用C++調(diào)用Python,然后將C++程序做成動(dòng)態(tài)鏈接庫 | 交互性較強(qiáng) | 需要用戶配置Python環(huán)境,實(shí)現(xiàn)方式復(fù)雜 |
| 利用C#命令行調(diào)用py文件 | 執(zhí)行速度快 | 需要用戶配置Python環(huán)境,交互性差 |
| 將python文件打包成exe進(jìn)行調(diào)用 | 無需安裝python運(yùn)行環(huán)境, | 執(zhí)行速度慢,傳遞數(shù)據(jù)復(fù)雜,交互性差 |
可以看出4種方式均有限制,很難同時(shí)滿足:交互性強(qiáng)、可調(diào)用第三方python庫、無需用戶配置Python環(huán)境要求,而這幾項(xiàng)要求恰恰是一款成熟軟件所必須的。而使用pythonnet庫可滿足以上三點(diǎn)要求。
本文均在.net 6環(huán)境下測試
使用pythonnet
- Nuget安裝
pythonnet - 設(shè)置
Runtime.PythonDLL屬性,即pythonxx.dll路徑,xx為版本號(hào) - 設(shè)置
PythonEngine.PythonHome,即python.exe所在路徑 - 設(shè)置
PythonEngine.PythonPath,python腳本所在目錄,可以放置多個(gè)路徑,以分號(hào)隔開,但是pathToVirtualEnv\Lib\site-packages和pathToVirtualEnv\Lib應(yīng)放在最后 - 調(diào)用
PythonEngine.Initialize();
string pathToVirtualEnv = ".\\envs\\pythonnetTest";
Runtime.PythonDLL = Path.Combine(pathToVirtualEnv, "python39.dll");
PythonEngine.PythonHome = Path.Combine(pathToVirtualEnv, "python.exe");
PythonEngine.PythonPath = $"{pathToVirtualEnv}\\Lib\\site-packages;{pathToVirtualEnv}\\Lib";
PythonEngine.Initialize();
//調(diào)用無參無返回值方法
using (Py.GIL()) //執(zhí)行python的調(diào)用應(yīng)該放在using (Py.GIL())塊內(nèi)
{
//python對(duì)象應(yīng)聲明為dynamic類型
dynamic np = Py.Import("test");
np.hello();
}
//調(diào)用有參有返回值方法
using (Py.GIL())
{
dynamic np = Py.Import("test");
int r = np.add(1, 2);
Console.WriteLine($"計(jì)算結(jié)果{r}");
}
python文件,必須放在PythonEngine.PythonPath設(shè)定的目錄下
def hello():
print("hello")
def add(a,b):
return a+b
嵌入Python環(huán)境及使用第三方庫
程序中包含Python腳本所需要的所有環(huán)境以及第三方庫可以免去用戶的自定義配置。本文使用Anaconda來構(gòu)建專用的虛擬環(huán)境。
- 創(chuàng)建專用虛擬環(huán)境(windows下首先切換到要建立虛擬環(huán)境的根目錄下),執(zhí)行
conda create --prefix=F:\condaenv\env_name python=3.7路徑及python版本根據(jù)需要自定義。 - 使用Anaconda Prompt,激活虛擬環(huán)境
conda activate F:\condaenv\env_name - 本次測試第三方庫Numpy(如果需要其他庫,安裝方法相同),安裝Numpy
pip install numpy
string pathToVirtualEnv = ".\\envs\\pythonnetTest";
Runtime.PythonDLL = Path.Combine(pathToVirtualEnv, "python39.dll");
PythonEngine.PythonHome = Path.Combine(pathToVirtualEnv, "python.exe");
PythonEngine.PythonPath = $"{pathToVirtualEnv}\\Lib\\site-packages;{pathToVirtualEnv}\\Lib";
PythonEngine.Initialize()
//使用第三方庫
using (Py.GIL())
{
dynamic np = Py.Import("numpy");
Console.WriteLine(np.cos(np.pi * 2));
dynamic sin = np.sin;
Console.WriteLine(sin(5));
double c = (double)(np.cos(5) + sin(5));
Console.WriteLine(c);
dynamic a = np.array(new List<float> { 1, 2, 3 });
Console.WriteLine(a.dtype);
dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
Console.WriteLine(b.dtype);
Console.WriteLine(a * b);
Console.ReadKey();
}

注意:C#和python對(duì)象進(jìn)行數(shù)學(xué)運(yùn)算時(shí),必須將Python對(duì)象放到前面,例如np.pi*2,不能是2*np.pi
傳遞對(duì)象
可以將C#對(duì)象傳遞到python中
在C#中定義對(duì)象
public class Person
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
string pathToVirtualEnv = ".\\envs\\pythonnetTest";
Runtime.PythonDLL = Path.Combine(pathToVirtualEnv, "python39.dll");
PythonEngine.PythonHome = Path.Combine(pathToVirtualEnv, "python.exe");
PythonEngine.PythonPath = $"{pathToVirtualEnv}\\Lib\\site-packages;{pathToVirtualEnv}\\Lib";
PythonEngine.Initialize();
//將C#中定義的類型傳入python
using (Py.GIL())
{
Person p = new Person("John", "Smith");
PyObject pyPerson = p.ToPython();
string r1 = test.FullName(pyPerson);
Console.WriteLine($"全名:{r1}");
}
python腳本
def FullName(p):
return p.FirstName+""+p.LastName

調(diào)用pyd文件
pyd文件主要有以下2點(diǎn)作用:
- 安全性更高:通過pyd生成的文件,已變成了dll文件,無法查看源碼
- 編譯成pyd后,性能會(huì)有提升
將.py文件編譯成pyd文件步驟如下:
1.pip install cython
2.在.py文件目錄下創(chuàng)建setup.py文件
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = "testName",
ext_modules = cythonize("test.py"), #將test.py文件編譯成pyd
)
3.執(zhí)行編譯命令
python setup.py build_ext --inplace
最后生成的pyd文件一般是test+cpython版本-平臺(tái)為文件名,可以重命名為test名稱,也可以不管,使用時(shí)仍然可以按test調(diào)用。
調(diào)動(dòng)pyd文件和調(diào)用py文件相同,但是執(zhí)行效率大大增強(qiáng),下文會(huì)對(duì)執(zhí)行速度進(jìn)行對(duì)比。
執(zhí)行速度對(duì)比
在test.py中定義一個(gè)耗時(shí)函數(shù)
import time
def Count():
start = time.perf_counter()
sum = 0
for i in range(10000):
for j in range(10000):
sum = sum + i + j
print("sum = ", sum)
end = time.perf_counter()
runTime = end - start
runTime_ms = runTime * 1000
print("運(yùn)行時(shí)間:", runTime, "秒")
直接執(zhí)行test.py腳本
運(yùn)行結(jié)果如下:

在C#中調(diào)用Conut()函數(shù)
//運(yùn)行時(shí)間測試
Console.WriteLine("C#開始計(jì)時(shí)");
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
test.Count();
stopWatch.Stop();
Console.WriteLine($"C#計(jì)時(shí)結(jié)束{stopWatch.ElapsedMilliseconds}");
執(zhí)行結(jié)果如下:

可以看到,使用pythonnet調(diào)用python腳本會(huì)有一定的性能損失,不過在對(duì)性能要求不是十分高的條件下是可以接受的。
執(zhí)行test.pyd文件
運(yùn)行結(jié)果如下:

從結(jié)果可以看出調(diào)用pyd比原生的py文件執(zhí)行還要快,所以可以使用pythonnet來執(zhí)行pyd文件,即實(shí)現(xiàn)代碼保護(hù)又提升了執(zhí)行效率。
以上就是C#/.net程序調(diào)用Python的教程分享的詳細(xì)內(nèi)容,更多關(guān)于C#調(diào)用Python的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#設(shè)置程序開機(jī)啟動(dòng)的實(shí)現(xiàn)示例
本文主要介紹了C#設(shè)置程序開機(jī)啟動(dòng)的實(shí)現(xiàn)示例,可以通過修改注冊(cè)表將啟動(dòng)信息寫入注冊(cè)表來實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
漢字轉(zhuǎn)拼音軟件制件示例(漢字轉(zhuǎn)字母)
這篇文章主要介紹了c#漢字轉(zhuǎn)拼音的方法,但不能判斷多音字,大家可以參考修改使用2014-01-01
使用C#表達(dá)式樹實(shí)現(xiàn)對(duì)象的深克隆(實(shí)例詳解)
C# 的表達(dá)式樹提供了一個(gè)強(qiáng)大的機(jī)制,可以將代碼以數(shù)據(jù)結(jié)構(gòu)的形式表示出來,使得代碼可以在運(yùn)行時(shí)進(jìn)行檢查、修改或執(zhí)行,這為動(dòng)態(tài)查詢生成、代碼優(yōu)化和動(dòng)態(tài)編程提供了很多可能性,這篇文章主要介紹了使用C#強(qiáng)大的表達(dá)式樹實(shí)現(xiàn)對(duì)象的深克隆,需要的朋友可以參考下2024-05-05
C#、ASP.NET通用擴(kuò)展工具類之LogicSugar
這篇文章主要介紹了C#、ASP.NET通用擴(kuò)展工具類之LogicSugar,本文直接給出實(shí)現(xiàn)代碼和使用方法示例,需要的朋友可以參考下2015-06-06
C# 繪制統(tǒng)計(jì)圖大全(柱狀圖, 折線圖, 扇形圖)
本篇文章介紹了C# 繪制統(tǒng)計(jì)圖大全,其中包括狀圖, 折線圖, 扇形圖,有需要的同學(xué)可以了解一下。2016-11-11

