DotNetPy:现代.NET 与 Python 互操作 实战指南
DotNetPy:现代.NET 与 Python 互操作 实战指南
常年深耕.NET生态的开发者,大多会遇到一个很实际的问题,那就是.NET在桌面开发、后端服务以及类型安全方面有着极强的优势,可碰到数据运算、AI推理、科学分析、爬虫脚本这类开发场景时,Python的生态优势又根本没法被替代,而想要让这两大技术栈结合使用,以往的互操作方案要么配置起来特别麻烦,要么兼容性很差,尤其是适配Native AOT、现代化文件式部署这类新功能的时候,整体使用起来更是力不从心。
今天要给大家介绍的DotNetPy,就是专门为现代.NET平台打造的轻量Python互操作工具,它能大幅简化.NET与Python之间的调用流程,既不用复杂的配置步骤,也不用编写多余的重复代码,就能实现进程内高效的双向互操作,还能完美兼容.NET 8及以上版本、Native AOT、文件式运行等多种现代化部署方式,这篇文章就带大家从零开始学习,全程结合实际操作,彻底掌握这套现代化的.NET与Python互操作方法。
一、DotNetPy 是什么?优势在哪?
DotNetPy(读音为 dot-net-pie)属于开源的.NET工具库,它的核心作用是搭建简单、贴合现代开发、低侵入的.NET与Python双向互操作能力,底层封装了Python C API,对外提供一套简洁好懂的托管调用接口,彻底丢掉了传统互操作方案里那些繁琐的配置步骤。
对比Python.NET、CSnakes这类同类型互操作工具,这款库的核心亮点十分明显:
-
不用写多余重复代码:不需要手动管理Python引擎的运行周期、GIL锁,API设计十分简洁,只需要短短几行代码就能完成整个调用流程
-
适配所有现代.NET版本:原生支持.NET 8/9/10各个版本,能完美实现Native AOT发布,同时还能兼容.NET 10文件式单文件运行的模式
-
环境打理更省事:自带uv集成功能,能够通过声明方式管控Python版本、依赖库文件,还能自动搭建好完整的Python运行环境
-
数据传递无阻碍:基础数据类型、集合、字典都能自动完成双向转换,不需要手动做序列化相关处理
-
自带安全检查:内置脚本注入检测功能,能够有效避开恶意脚本运行带来的安全隐患
说白了,以往需要编写几十行代码才能实现的.NET调用Python逻辑,借助DotNetPy只需要几行代码就能搞定,而且部署方式更灵活,版本之间的兼容效果也更好。
二、环境准备:快速搭建开发环境
1. 基础环境配置要求
-
.NET SDK 8.0及以上版本(优先推荐.NET 10,体验文件式运行的相关功能)
-
Python 3.10及以上版本(建议搭配uv工具,打理环境的效率会更高)
-
Windows、Linux、macOS全平台都能正常使用
-
可以使用雨云(云服务器)作为搭建工具:每日签到,签到一个月可以换一周的云服务器,并且无限制,签到1年可以拿到3个月的云服务器时间,有国内、香港、美国、日本的云服务器可供选择,点击注册:雨云注册。
2. 项目引入DotNetPy依赖
新建控制台或者ASP.NET Core项目之后,大家可以通过NuGet安装核心程序包,同时也能根据自身需求安装UV集成扩展,这款扩展强烈推荐安装,能大幅简化Python环境的打理工作。
# 安装核心库 Install-Package DotNetPy # 安装UV环境管理扩展(可选,强烈推荐) Install-Package DotNetPy.Uv
安装完成之后,不需要再做额外的复杂配置,直接在代码里引用对应的命名空间,就可以开启后续的开发工作。
三、基础实战:.NET 调用 Python 核心用法
接下来我们从最简单的使用场景入手,一步步演示DotNetPy的核心使用方法,这些方法能够覆盖日常开发里的绝大多数业务场景。
1. 引擎初始化与基础表达式运行
第一步我们先完成Python引擎的初始化操作,DotNetPy既支持自动扫描本地的Python环境,也可以手动指定Python运行库的路径,能够很好适配离线部署这类特殊的使用场景。
using DotNetPy; // 方式1:自动探测本地Python环境(推荐,无需手动配置路径) Python.Initialize(); // 方式2:手动指定Python运行库路径(离线部署、指定特定Python版本时使用) // var pythonPath = @"C:\Python313\python313.dll"; // Python.Initialize(pythonPath); // 获取执行器实例 var executor = Python.GetInstance(); // 直接执行Python表达式,获取返回结果 var sumResult = executor.Evaluate("sum([1,2,3,4,5,6])")?.GetInt32(); Console.WriteLine($"表达式计算结果:{sumResult}"); // 执行简单Python语句 executor.Execute("print('Hello from Python!');
运行项目之后,大家可以直接看到Python的输出内容以及表达式的运算结果,全程没有任何多余的代码,新手也能毫无门槛快速上手。
2. 传输.NET数据至Python,运行复杂脚本
日常开发过程中,我们大多需要将.NET中的数据传递给Python,调用Python各类库完成运算处理后,再将结果回传到.NET端,而DotNetPy支持字典形式传递参数,还能自动完成数据类型的映射转换。
// 构造.NET数据 var scoreList = new[] { 88, 92, 76, 98, 85, 90 }; // 编写Python脚本,接收参数并计算 var pythonScript = @" import statistics # 接收.NET传入的data参数,完成统计计算 avg_score = statistics.mean(data) max_score = max(data) min_score = min(data) # 将结果存入result字典,方便.NET捕获 result = { 'avg': avg_score, 'max': max_score, 'min': min_score } "; // 执行脚本并捕获result变量 using var result = executor.ExecuteAndCapture( pythonScript, // 以字典形式传递参数,key对应Python中的变量名 new Dictionary<string, object?> { { "data", scoreList } } ); // 从Python结果中获取数据,强类型转换 var avg = result?.GetDouble("avg"); var max = result?.GetInt32("max"); var min = result?.GetInt32("min"); Console.WriteLine($"平均分:{avg:F2},最高分:{max},最低分:{min}");
这种调用方式灵活性极强,不管是数组、列表、字典还是基础数据类型,都能实现无缝传递对接,Python脚本编写完成后可以直接嵌入.NET代码中,不需要单独维护独立的.py脚本文件。
3. 调用Python第三方库(NumPy/Pandas/AI模型)
DotNetPy最核心的价值,就是让.NET开发者能够轻松调用Python体系中庞大的第三方资源,拿日常开发常用的NumPy来说,大家只需要在Python脚本中导入对应模块,就能正常使用相关功能。
var numpyScript = @" import numpy as np # 使用NumPy进行数组计算 arr = np.array(data) result = { 'mean': np.mean(arr), 'std': np.std(arr), 'sum': np.sum(arr) } "; var data = new double[] { 1.2, 2.3, 3.4, 4.5, 5.6 }; using var numpyResult = executor.ExecuteAndCapture(numpyScript, new Dictionary<string, object?> { { "data", data } }); Console.WriteLine($"均值:{numpyResult?.GetDouble("mean"):F2},标准差:{numpyResult?.GetDouble("std"):F2}");
小贴士:大家提前通过pip或者uv工具安装好对应的Python依赖库,就能正常调用相关功能,Pandas、Scikit-learn、PyTorch模型推理等场景的使用方式也完全一致。
四、进阶实战:声明式Python环境管理
项目部署上线的时候,Python环境不统一、依赖包版本不一致一直是让人头疼的问题,而DotNetPy自带UV集成功能,能够在.NET代码中通过声明方式打理Python环境,自动下载Python安装包、创建虚拟环境、安装第三方依赖,从根本上解决环境不一致的难题。
using DotNetPy; using DotNetPy.Uv; // 构建Python环境配置 var pythonProject = PythonProject.CreateBuilder() .WithProjectName("dotnet-python-demo") // 指定Python版本要求 .WithPythonVersion(">=3.10") // 声明需要安装的Python依赖包 .AddDependencies("numpy>=1.24.0", "pandas>=2.0.0") .Build(); // 自动初始化环境:下载Python、创建虚拟环境、安装依赖 await pythonProject.InitializeAsync(); // 获取专属执行器 var uvExecutor = pythonProject.GetExecutor(); // 后续调用逻辑和基础用法完全一致 var testData = new[] { 1, 2, 3, 4, 5 }; using var res = uvExecutor.ExecuteAndCapture(@" import numpy as np result = {'sum': np.sum(data)} ", new Dictionary<string, object?> { { "data", testData } }); Console.WriteLine($"NumPy求和结果:{res?.GetInt32("sum")}");
这种方式特别适合团队协作和服务器批量部署,不需要手动配置Python环境,运行项目时会自动完成环境搭建,彻底杜绝本地运行正常、部署上线就报错的尴尬情况。
五、生产环境注意事项
1. 安全问题
DotNetPy运行Python脚本的权限和.NET进程完全相同,因此严禁直接运行用户输入的未知脚本,以此防范代码注入带来的安全漏洞,正确的处理方式是固定Python脚本的逻辑,只通过参数传递用户数据,不要让用户自定义脚本逻辑。
// 错误用法:直接执行用户输入,存在极大安全风险 // uvExecutor.Execute(userInput); // 正确用法:脚本固定,仅传递参数 uvExecutor.Execute("result = sum(numbers)", new Dictionary<string, object?> { { "numbers", userData } });
2. 资源释放
ExecuteAndCapture方法返回的结果对象,全都实现了IDisposable接口,建议大家搭配using语句使用,这样就能自动释放Python对象资源,避免出现内存泄漏的问题。
3. Native AOT发布
DotNetPy本身就支持Native AOT发布,大家只需要在项目配置文件中开启PublishAot选项,就能打包成原生单文件程序,部署的时候不需要安装.NET运行时,再配合UV环境打理功能,就能实现全程离线部署。
六、适用场景总结
DotNetPy非常适用于以下几类.NET开发场景:
-
.NET后端服务调用Python AI模型、数据分析处理相关功能
-
桌面客户端集成Python脚本、爬虫、数据处理相关业务逻辑
-
需要Native AOT、轻量部署的互操作开发场景
-
不想编写冗余互操作代码、追求简洁开发的各类场景
对比传统的互操作方案,这款工具在现代版本适配、轻量化使用、上手难度方面优势显著,也是当下.NET生态中,适配现代化开发流程的优质互操作工具。
七、写在最后
如今跨语言开发越来越普遍,.NET与Python结合使用,能让项目同时具备出色的运行性能和完善的生态支持,而DotNetPy凭借简洁的设计,打通了两大技术栈之间的调用壁垒,不管是开发日常小工具,还是上线生产环境的项目,都能轻松上手且稳定运行。
这篇文章完整讲解了从基础入门到生产部署的全流程实战内容,大家可以直接复制代码运行测试,快速将这项技术应用到自身项目中,后续我也会持续分享更多.NET与Python互操作的实战案例,欢迎大家留言交流探讨。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)