C#/.net程序调用python

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

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

  1. Nuget安装pythonnet
  2. 设置Runtime.PythonDLL属性,即pythonxx.dll路径,xx为版本号
  3. 设置PythonEngine.PythonHome,即python.exe所在路径
  4. 设置PythonEngine.PythonPath,python脚本所在目录,可以放置多个路径,以分号隔开,但是pathToVirtualEnv\Lib\site-packages和pathToVirtualEnv\Lib应放在最后
  5. 调用PythonEngine.Initialize();

stringpathToVirtualEnv="C:\\Users\\cni23287938\\.conda\\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来构建专用的虚拟环境。

  1. 创建专用虚拟环境(windows下首先切换到要建立虚拟环境的根目录下),执行conda create --prefix=F:\condaenv\env_name python=3.7路径及python版本根据需要自定义。
  2. 使用Anaconda Prompt,激活虚拟环境conda activate F:\condaenv\env_name
  3. 本次测试第三方库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();

}


  1. 注意: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#中定义的类型传入python

using (Py.GIL())

{

   Personp=newPerson("John", "Smith");

   PyObjectpyPerson=p.ToPython();

   stringr1=test.FullName(pyPerson);

   Console.WriteLine($"全名:{r1}");

}

python脚本

defFullName(p):

   returnp.FirstName+""+p.LastName

调用pyd文件

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

  1. 安全性更高:通过pyd生成的文件,已变成了dll文件,无法查看源码
  2. 编译成pyd后,性能会有提升

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

  1. pip install cython
  2. 在.py文件目录下创建setup.py文件

fromdistutils.coreimportsetup

fromCython.Buildimportcythonize

setup(

name="testName",

ext_modules=cythonize("test.py"), #将test.py文件编译成pyd

)

  1. 执行编译命令

python setup.py build_ext --inplace

最后生成的pyd文件一般是test+cpython版本-平台为文件名,可以重命名为test名称,也可以不管,使用时仍然可以按test调用。

调动pyd文件和调用py文件相同,但是执行效率大大增强,下文会对执行速度进行对比。

执行速度对比

在test.py中定义一个耗时函数

importtime

defCount():

   start=time.perf_counter()

   sum=0

   foriinrange(10000):

       forjinrange(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#开始计时");

StopwatchstopWatch=newStopwatch();

stopWatch.Start();

test.Count();

stopWatch.Stop();

Console.WriteLine($"C#计时结束{stopWatch.ElapsedMilliseconds}");

执行结果如下:

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

  • 执行test.pyd文件,运行结果如下:

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

目录
打赏
0
0
0
0
128
分享
相关文章
CUDA重大更新:原生Python可直接编写高性能GPU程序
NVIDIA在2025年GTC大会上宣布CUDA并行计算平台正式支持原生Python编程,消除了Python开发者进入GPU加速领域的技术壁垒。这一突破通过重新设计CUDA开发模型,引入CUDA Core、cuPyNumeric、NVMath Python等核心组件,实现了Python与GPU加速的深度集成。开发者可直接用Python语法进行高性能并行计算,显著降低门槛,扩展CUDA生态,推动人工智能、科学计算等领域创新。此更新标志着CUDA向更包容的语言生态系统转型,未来还将支持Rust、Julia等语言。
230 3
CUDA重大更新:原生Python可直接编写高性能GPU程序
Playwright 多语言一体化——Python/Java/.NET 全栈采集实战
本文以反面教材形式,剖析了在使用 Playwright 爬取懂车帝车友圈问答数据时常见的配置错误(如未设置代理、Cookie 和 User-Agent),并提供了 Python、Java 和 .NET 三种语言的修复代码示例。通过错误示例 → 问题剖析 → 修复过程 → 总结教训的完整流程,帮助读者掌握如何正确配置爬虫代理及其它必要参数,避免 IP 封禁和反爬检测,实现高效数据采集与分析。
141 3
Playwright 多语言一体化——Python/Java/.NET 全栈采集实战
C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
本文分析了C#程序操作Sql Server数据库时偶发的不返回、不抛异常问题,并提出了解决思路。首先解析了一个执行存储过程的函数`ExecuteProcedure`,其功能是调用存储过程并返回影响行数。针对代码执行被阻塞但无异常的情况,文章总结了可能原因,如死锁、无限循环或网络问题等。随后提供了多种解决方案:1) 增加日志定位问题;2) 使用异步操作提升响应性;3) 设置超时机制避免阻塞;4) 利用线程池分离主线程;5) 通过信号量同步线程;6) 监控数据库连接状态确保可用性。这些方法可有效应对数据库操作中的潜在问题,保障程序稳定性。
223 11
Playwright多语言生态:跨Python/Java/.NET的统一采集方案
随着数据采集需求的增加,传统爬虫工具如Selenium、Jsoup等因语言割裂、JS渲染困难及代理兼容性差等问题,难以满足现代网站抓取需求。微软推出的Playwright框架,凭借多语言支持(Python/Java/.NET/Node.js)、统一API接口和优异的JS兼容性,解决了跨语言协作、动态页面解析和身份伪装等痛点。其性能优于Selenium与Puppeteer,在学术数据库(如Scopus)抓取中表现出色。行业应用广泛,涵盖高校科研、大型数据公司及AI初创团队,助力构建高效稳定的爬虫系统。
182 2
Playwright多语言生态:跨Python/Java/.NET的统一采集方案
如何运用C#.NET技术快速开发一套掌上医院系统?
本方案基于C#.NET技术快速构建掌上医院系统,结合模块化开发理念与医院信息化需求。核心功能涵盖用户端的预约挂号、在线问诊、报告查询等,以及管理端的排班管理和数据统计。采用.NET Core Web API与uni-app实现前后端分离,支持跨平台小程序开发。数据库选用SQL Server 2012,并通过读写分离与索引优化提升性能。部署方案包括Windows Server与负载均衡设计,确保高可用性。同时针对API差异、数据库老化及高并发等问题制定应对措施,保障系统稳定运行。推荐使用Postman、Redgate等工具辅助开发,提升效率与质量。
144 0
|
5月前
|
[oeasy]python074_ai辅助编程_水果程序_fruits_apple_banana_加法_python之禅
本文回顾了从模块导入变量和函数的方法,并通过一个求和程序实例,讲解了Python中输入处理、类型转换及异常处理的应用。重点分析了“明了胜于晦涩”(Explicit is better than implicit)的Python之禅理念,强调代码应清晰明确。最后总结了加法运算程序的实现过程,并预告后续内容将深入探讨变量类型的隐式与显式问题。附有相关资源链接供进一步学习。
71 4
在Python程序中实现LevelDB的海量key的分批次扫描
通过本文的步骤,您可以在Python程序中实现对LevelDB海量key的分批次扫描。这样不仅能够有效地管理大规模数据,还可以避免一次性加载过多数据到内存中,提高程序的性能和稳定性。希望这篇指南能为您的开发工作提供实用的帮助。
147 28
C#/.NET/.NET Core拾遗补漏合集(24年12月更新)
C#/.NET/.NET Core拾遗补漏合集(24年12月更新)
106 6
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
101 6
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
106 6

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问