<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
C#/.net程式呼叫python
C#的優勢在於window下的開發,不僅功能強大而且開發週期短。而python則有眾多的第三方庫,可以避免自己造輪子,利用C#來做介面,而具體實現使用python來實現可以大大提高開發效率。本文介紹如何使用pythonnet
來執行python指令碼,使用pythonnet
既可以具有較高的互動性,又可以使用第三方python庫,同時可以將程式需要的python環境及第三方庫打包到軟體中,避免使用者進行python的環境設定。
呼叫python常見的方法有4種
方式 | 優點 | 缺點 |
---|---|---|
使用IronPython | 無需安裝python執行環境,互動性強,C#和python無縫連線 | 某些python第三方庫不支援,如numpy |
使用C++呼叫Python,然後將C++程式做成動態連結庫 | 互動性較強 | 需要使用者設定Python環境,實現方式複雜 |
利用C#命令列呼叫py檔案 | 執行速度快 | 需要使用者設定Python環境,互動性差 |
將python檔案打包成exe進行呼叫 | 無需安裝python執行環境, | 執行速度慢,傳遞資料複雜,互動性差 |
可以看出4種方式均有限制,很難同時滿足:互動性強、可呼叫第三方python庫、無需使用者設定Python環境要求,而這幾項要求恰恰是一款成熟軟體所必須的。而使用pythonnet
庫可滿足以上三點要求。
本文均在.net 6環境下測試
pythonnet
Runtime.PythonDLL
屬性,即pythonxx.dll路徑,xx為版本號PythonEngine.PythonHome
,即python.exe所在路徑PythonEngine.PythonPath
,python指令碼所在目錄,可以放置多個路徑,以分號隔開,但是pathToVirtualEnvLibsite-packages和pathToVirtualEnvLib應放在最後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(); //呼叫無參無返回值方法 using (Py.GIL()) //執行python的呼叫應該放在using (Py.GIL())塊內 { //python物件應宣告為dynamic型別 dynamic np = Py.Import("test"); np.hello(); } //呼叫有參有返回值方法 using (Py.GIL()) { dynamic np = Py.Import("test"); int r = np.add(1, 2); Console.WriteLine($"計算結果{r}"); }
python檔案,必須放在PythonEngine.PythonPath
設定的目錄下
def hello(): print("hello") def add(a,b): return a+b
程式中包含Python指令碼所需要的所有環境以及第三方庫可以免去使用者的自定義設定。本文使用Anaconda來構建專用的虛擬環境。
conda create --prefix=F:condaenvenv_name python=3.7
路徑及python版本根據需要自定義。conda activate F:condaenvenv_name
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物件進行數學運算時,必須將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點作用:
將.py檔案編譯成pyd檔案步驟如下:
1.pip install cython
2.在.py檔案目錄下建立setup.py檔案
from distutils.core import setup from Cython.Build import cythonize setup( name = "testName", ext_modules = cythonize("test.py"), #將test.py檔案編譯成pyd )
3.執行編譯命令
python setup.py build_ext --inplace
最後生成的pyd檔案一般是test+cpython版本-平臺為檔名,可以重新命名為test名稱,也可以不管,使用時仍然可以按test呼叫。
調動pyd檔案和呼叫py檔案相同,但是執行效率大大增強,下文會對執行速度進行對比。
在test.py中定義一個耗時函數
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, "秒")
直接執行test.py指令碼
執行結果如下:
在C#中呼叫Conut()函數
//執行時間測試 Console.WriteLine("C#開始計時"); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); test.Count(); stopWatch.Stop(); Console.WriteLine($"C#計時結束{stopWatch.ElapsedMilliseconds}");
執行結果如下:
可以看到,使用pythonnet呼叫python指令碼會有一定的效能損失,不過在對效能要求不是十分高的條件下是可以接受的。
執行test.pyd檔案
執行結果如下:
從結果可以看出呼叫pyd比原生的py檔案執行還要快,所以可以使用pythonnet來執行pyd檔案,即實現程式碼保護又提升了執行效率。
以上就是C#/.net程式呼叫Python的教學分享的詳細內容,更多關於C#呼叫Python的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45