专业编程基础技术教程

网站首页 > 基础教程 正文

C#和Python强强联姻 做大做强(c#与python联合)

ccvgpt 2025-03-28 15:14:29 基础教程 17 ℃

前言

C#和Python是当下比较流行的两门编程语言。C#作为微软的当家花旦,而Python作为AI的当家花旦,当两者强强联合,发生碰撞的时候,势必会产生一些好玩的东西。

前提条件

C#要集成Python,需要用户电脑上安装Python。当然这个未必有点强人所难,一般用户也不太能愿意自己去安装Python。鉴于这种情况,开发人员可以去Python官网下载嵌入版本的Python压缩包。本篇基于官网下载的Python3.11嵌入版本压缩包为例展开。

C#和Python强强联姻 做大做强(c#与python联合)

嵌入版解压后大小约为20M,没有pip。需要pip的小伙,可以搜索get-pip.py,单独安装。pip安装后,需要额外占用大概20M空间。安装目录下会多出Lib和Scripts两个文件夹。

最后交付给用户的时候,把嵌入版本的Python一并打包发给用户。

新建C#工程

在Visual Studio中新建C#项目。Pythonnet支持.Net Framework和.Net6及之前的版本。尝试用.Net8,看起来Pythonnet暂时还不支持.Net8。这里选择.Net6为例新建项目。

在NuGet包管理器中安装Pythonnet,当前最新版本为3.0.3。

配置Python运行参数

为了让Pythonnet找到执行对应的Python,我们还需要设置几个Python路径。

Runtime.PythonDll

Pythonxx.dll对应的全路径

PythonEngine.PythonPath

Python内置库路径,自定义Python脚本路径

using Python.Runtime;

// 内嵌版Python所在目录
string pyDir = @"E:\Programs\python311";
Runtime.PythonDLL = Path.Combine(pyDir, "python311.dll");
// python311.zip是Python内嵌版内置库的位置
// Lib\site-packages, 通过pip安装的第三方包存放位置
// .\py,自己写的Python脚本所在位置
PythonEngine.PythonPath = $@".\py;{pyDir};{pyDir}\python311.zip;{pyDir}\Lib\site-packages";
PythonEngine.Initialize(); 

调用Python代码

Pythonnet提供了很多调用Python的方法。对Python的调用方法要放在using(Py.GIL()) {}方法快中。

  • Py.Import("xx"),导入Python包,可以是Python内置的模块,或者通过pip安装的第三方模块,也可以是自己写的Python模块,然后就可以调用相应模块提供的方法。
using (Py.GIL())
{
    dynamic np = Py.Import("numpy");
    Console.WriteLine(np.cos(np.pi * 2));

    dynamic a = np.array(new List { 1, 2, 3 });
    Console.WriteLine(a.dtype);

    dynamic test = Py.Import("test"); // 自定义的模块,放在.\py\test.py文件中
    int r = test.add(1, 2);
    Console.WriteLine($"计算结果{r}");
    test.hello();
}
  • Py.CreateScope(),通过返回的scope对象,直接执行自定义的Python代码。我们可以执行复杂的Python代码,然后在C#中从Python获取数据
using(Py.GIL())
{
    using var scope = Py.CreateScope();
    scope.Exec(@"items = [1, True, 'message']");
    Console.WriteLine(scope.Eval("items"));

    // 执行Python代码
    scope.Exec(@"
import random
import secrets
items = [secrets.token_hex(random.randint(10,20)) for i in range(5)]
");
    Console.WriteLine(scope.Eval("items"));
}

Tags:

最近发表
标签列表