您好,登錄后才能下訂單哦!
這篇文章主要介紹了怎么使用C#/.net程序調(diào)用Python的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么使用C#/.net程序調(diào)用Python文章都會有所收獲,下面我們一起來看看吧。
C#/.net程序調(diào)用python
C#的優(yōu)勢在于window下的開發(fā),不僅功能強大而且開發(fā)周期短。而python則有眾多的第三方庫,可以避免自己造輪子,利用C#來做界面,而具體實現(xiàn)使用python來實現(xiàn)可以大大提高開發(fā)效率。本文介紹如何使用pythonnet
來執(zhí)行python腳本,使用pythonnet
既可以具有較高的交互性,又可以使用第三方python庫,同時可以將程序需要的python環(huán)境及第三方庫打包到軟件中,避免用戶進(jìn)行python的環(huán)境配置。
調(diào)用python常見的方法有4種
方式 | 優(yōu)點 | 缺點 |
---|---|---|
使用IronPython | 無需安裝python運行環(huán)境,交互性強,C#和python無縫連接 | 某些python第三方庫不支持,如numpy |
使用C++調(diào)用Python,然后將C++程序做成動態(tài)鏈接庫 | 交互性較強 | 需要用戶配置Python環(huán)境,實現(xiàn)方式復(fù)雜 |
利用C#命令行調(diào)用py文件 | 執(zhí)行速度快 | 需要用戶配置Python環(huán)境,交互性差 |
將python文件打包成exe進(jìn)行調(diào)用 | 無需安裝python運行環(huán)境, | 執(zhí)行速度慢,傳遞數(shù)據(jù)復(fù)雜,交互性差 |
可以看出4種方式均有限制,很難同時滿足:交互性強、可調(diào)用第三方python庫、無需用戶配置Python環(huán)境要求,而這幾項要求恰恰是一款成熟軟件所必須的。而使用pythonnet
庫可滿足以上三點要求。
本文均在.net 6環(huán)境下測試
Nuget安裝pythonnet
設(shè)置Runtime.PythonDLL
屬性,即pythonxx.dll路徑,xx為版本號
設(shè)置PythonEngine.PythonHome
,即python.exe所在路徑
設(shè)置PythonEngine.PythonPath
,python腳本所在目錄,可以放置多個路徑,以分號隔開,但是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對象應(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($"計算結(jié)果{r}"); }
python文件,必須放在PythonEngine.PythonPath
設(shè)定的目錄下
def hello(): print("hello") def add(a,b): return a+b
程序中包含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(如果需要其他庫,安裝方法相同),安裝Numpypip 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對象進(jìn)行數(shù)學(xué)運算時,必須將Python對象放到前面,例如np.pi*2,不能是2*np.pi
可以將C#對象傳遞到python中
在C#中定義對象
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
pyd文件主要有以下2點作用:
安全性更高:通過pyd生成的文件,已變成了dll文件,無法查看源碼
編譯成pyd后,性能會有提升
將.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版本-平臺為文件名,可以重命名為test名稱,也可以不管,使用時仍然可以按test調(diào)用。
調(diào)動pyd文件和調(diào)用py文件相同,但是執(zhí)行效率大大增強,下文會對執(zhí)行速度進(jìn)行對比。
在test.py中定義一個耗時函數(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("運行時間:", runTime, "秒")
直接執(zhí)行test.py腳本
運行結(jié)果如下:
在C#中調(diào)用Conut()函數(shù)
//運行時間測試 Console.WriteLine("C#開始計時"); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); test.Count(); stopWatch.Stop(); Console.WriteLine($"C#計時結(jié)束{stopWatch.ElapsedMilliseconds}");
執(zhí)行結(jié)果如下:
可以看到,使用pythonnet調(diào)用python腳本會有一定的性能損失,不過在對性能要求不是十分高的條件下是可以接受的。
執(zhí)行test.pyd文件
運行結(jié)果如下:
從結(jié)果可以看出調(diào)用pyd比原生的py文件執(zhí)行還要快,所以可以使用pythonnet來執(zhí)行pyd文件,即實現(xiàn)代碼保護(hù)又提升了執(zhí)行效率。
關(guān)于“怎么使用C#/.net程序調(diào)用Python”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“怎么使用C#/.net程序調(diào)用Python”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。