怎么使用C#/.net程序调用Python(python,开发技术)

时间:2024-04-29 12:12:45 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

C#/.net程序调用python

C#的优势在于window下的开发,不仅功能强大而且开发周期短。而python则有众多的第三方库,可以避免自己造轮子,利用C#来做界面,而具体实现使用python来实现可以大大提高开发效率。本文介绍如何使用pythonnet来执行python脚本,使用pythonnet既可以具有较高的交互性,又可以使用第三方python库,同时可以将程序需要的python环境及第三方库打包到软件中,避免用户进行python的环境配置。

C#调用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

  • Nuget安装pythonnet

  • 设置Runtime.PythonDLL属性,即pythonxx.dll路径,xx为版本号

  • 设置PythonEngine.PythonHome,即python.exe所在路径

  • 设置PythonEngine.PythonPath,python脚本所在目录,可以放置多个路径,以分号隔开,但是pathToVirtualEnv\Lib\site-packages和pathToVirtualEnv\Lib应放在最后

  • 调用PythonEngine.Initialize();

stringpathToVirtualEnv=".\\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类型dynamicnp=Py.Import("test");np.hello();}//调用有参有返回值方法using(Py.GIL()){dynamicnp=Py.Import("test");intr=np.add(1,2);Console.WriteLine($"计算结果{r}");}

python文件,必须放在PythonEngine.PythonPath设定的目录下

defhello():print("hello")defadd(a,b):returna+b

嵌入Python环境及使用第三方库

程序中包含Python脚本所需要的所有环境以及第三方库可以免去用户的自定义配置。本文使用Anaconda来构建专用的虚拟环境。

  • 创建专用虚拟环境(windows下首先切换到要建立虚拟环境的根目录下),执行conda create --prefix=F:\condaenv\env_name python=3.7路径及python版本根据需要自定义。

  • 使用Anaconda Prompt,激活虚拟环境conda activate F:\condaenv\env_name

  • 本次测试第三方库Numpy(如果需要其他库,安装方法相同),安装Numpypip install numpy

stringpathToVirtualEnv=".\\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()){dynamicnp=Py.Import("numpy");Console.WriteLine(np.cos(np.pi*2));dynamicsin=np.sin;Console.WriteLine(sin(5));doublec=(double)(np.cos(5)+sin(5));Console.WriteLine(c);dynamica=np.array(newList<float>{1,2,3});Console.WriteLine(a.dtype);dynamicb=np.array(newList<float>{6,5,4},dtype:np.int32);Console.WriteLine(b.dtype);Console.WriteLine(a*b);Console.ReadKey();}

怎么使用C#/.net程序调用Python

注意:C#和python对象进行数学运算时,必须将Python对象放到前面,例如np.pi*2,不能是2*np.pi

传递对象

可以将C#对象传递到python中

在C#中定义对象

publicclassPerson{publicPerson(stringfirstName,stringlastName){FirstName=firstName;LastName=lastName;}publicstringFirstName{get;set;}publicstringLastName{get;set;}}
stringpathToVirtualEnv=".\\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#中定义的类型传入pythonusing(Py.GIL()){Personp=newPerson("John","Smith"); PyObjectpyPerson=p.ToPython(); stringr1=test.FullName(pyPerson); Console.WriteLine($"全名:{r1}");}

python脚本

defFullName(p):returnp.FirstName+""+p.LastName

怎么使用C#/.net程序调用Python

调用pyd文件

pyd文件主要有以下2点作用:

  • 安全性更高:通过pyd生成的文件,已变成了dll文件,无法查看源码

  • 编译成pyd后,性能会有提升

将.py文件编译成pyd文件步骤如下:

1.pip install cython

2.在.py文件目录下创建setup.py文件

fromdistutils.coreimportsetupfromCython.Buildimportcythonizesetup(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中定义一个耗时函数

importtimedefCount():start=time.perf_counter()sum=0foriinrange(10000):forjinrange(10000):sum=sum+i+jprint("sum=",sum)end=time.perf_counter()runTime=end-startrunTime_ms=runTime*1000print("运行时间:",runTime,"秒")

直接执行test.py脚本

运行结果如下:

怎么使用C#/.net程序调用Python

在C#中调用Conut()函数

//运行时间测试Console.WriteLine("C#开始计时");StopwatchstopWatch=newStopwatch();stopWatch.Start();test.Count();stopWatch.Stop();Console.WriteLine($"C#计时结束{stopWatch.ElapsedMilliseconds}");

执行结果如下:

怎么使用C#/.net程序调用Python

可以看到,使用pythonnet调用python脚本会有一定的性能损失,不过在对性能要求不是十分高的条件下是可以接受的。

执行test.pyd文件

运行结果如下:

怎么使用C#/.net程序调用Python

从结果可以看出调用pyd比原生的py文件执行还要快,所以可以使用pythonnet来执行pyd文件,即实现代码保护又提升了执行效率。

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:怎么使用C#/.net程序调用Python的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Docker容器网络更改如何实现下一篇:

13 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18