在c#中调用python有几种方式:1、pc已经安装了python环境,使用 Process
类执行 Python 脚本。
2、 使用 IronPython(嵌入式 Python 解释器)
3、使用 Python.NET(C# 和 Python 的双向互操作)4、其它方式(如http、socket等)因为我项目使用python.net方式,这里介绍python.net相关使用。
Python.NET 是一个强大的库,允许 C# 和 Python 之间进行双向互操作。它支持直接加载 Python 模块并在 C# 中调用其函数。
首先需要python环境,一种直接pc安装python环境,赋值path变量,第二种使用python离线包,打包到项目中。下面是我wpf中测试demo 帮助类 代码如下:
using Python.Runtime;
using System;
using System.IO;
namespace ClassLibraryPython
{
public static class PythonInterpreter
{
// 标记 Python 引擎是否已初始化
private static bool _isInitialized = false;
/// <summary>
/// 初始化 Python 引擎。
/// </summary>
public static void Initialize()
{
if (_isInitialized)
{
Console.WriteLine("Python 引擎已初始化,无需重复初始化。");
return;
}
try
{
string pathToVirtualEnv = @"C:\Users\Admin\miniconda3\envs\PythonProject2_3.10";
string pathToPythonProject = "D:\\lion\\python\\PythonProject2"; // 添加Python文件所在的目录
// 设置Python DLL路径和Python安装路径
String dllPath = Path.Combine(pathToVirtualEnv, "python310.dll");
Runtime.PythonDLL = dllPath;
Environment.SetEnvironmentVariable("PATH", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToVirtualEnv, EnvironmentVariableTarget.Process);
PythonEngine.PythonHome = Environment.GetEnvironmentVariable("PYTHONHOME", EnvironmentVariableTarget.Process);
PythonEngine.PythonPath = $"{pathToVirtualEnv}\\Lib\\site-packages;{pathToVirtualEnv}\\Lib;{pathToPythonProject}"; // 将Python文件所在的目录添加到Python路径中
// 初始化 Python 引擎
PythonEngine.Initialize();
_isInitialized = true;
Console.WriteLine("Python 引擎初始化成功!");
}
catch (Exception ex)
{
Console.WriteLine($"Python 引擎初始化失败:{ex.Message}");
throw;
}
}
/// <summary>
/// 销毁 Python 引擎。
/// </summary>
public static void Shutdown()
{
if (!_isInitialized)
{
Console.WriteLine("Python 引擎尚未初始化,无法销毁。");
return;
}
try
{
// 销毁 Python 引擎
PythonEngine.Shutdown();
_isInitialized = false;
Console.WriteLine("Python 引擎已成功销毁!");
}
catch (Exception ex)
{
Console.WriteLine($"Python 引擎销毁失败:{ex.Message}");
throw;
}
}
/// <summary>
/// 执行一段 Python 代码。
/// </summary>
/// <param name="code">要执行的 Python 代码字符串。</param>
public static void Execute(string code)
{
if (!_isInitialized)
{
Console.WriteLine("Python 引擎尚未初始化,请先调用 Initialize 方法。");
return;
}
try
{
using (Py.GIL()) // 获取全局解释器锁
{
PythonEngine.Exec(code); // 执行 Python 代码
}
}
catch (Exception ex)
{
Console.WriteLine($"执行 Python 代码失败:{ex.Message}");
throw;
}
}
/// <summary>
/// 导入 Python 模块。
/// </summary>
/// <param name="moduleName">模块名称。</param>
/// <returns>动态类型的模块对象。</returns>
public static dynamic ImportModule(string moduleName)
{
if (!_isInitialized)
{
Console.WriteLine("Python 引擎尚未初始化,请先调用 Initialize 方法。");
return null;
}
try
{
using (Py.GIL()) // 获取全局解释器锁
{
return Py.Import(moduleName); // 导入 Python 模块
}
}
catch (Exception ex)
{
Console.WriteLine($"导入 Python 模块失败:{ex.Message}");
throw;
}
}
}
}
这里是一个工具类,初始化python的虚拟机和python模块的位置,其中pathToPythonProject是我们代码位置,引入后就可以直接调用。其中我的python脚本代码放置在这个目录下(pathToPythonProject),TModule.py代码如下:
def add(a,b):
return a+b
def sub(a,b):
return a-b
def mul(a,b):
return a*b
def div(a,b):
return a/b
def mod(a,b):
return a%b
def pow(a,b):
return a**b
def sqrt(a):
return a**0.5
def main():
print("Welcome to the calculator")
print("1.Add")
print("2.Sub")
print("3.Mul")
print("4.Div")
print("5.Mod")
print("6.Pow")
print("7.Sqrt")
print("8.Exit")
下面是wpf中的界面代码:
using ClassLibraryPython;
using demo.interfaceNamespace;
using Python.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace demo
{
/// <summary>
/// Command.xaml 的交互逻辑
/// </summary>
public partial class Command : Window
{
public static RoutedCommand MyNewCommand = new RoutedCommand();
public Command()
{
InitializeComponent();
this.CommandBindings.Add(new CommandBinding(MyNewCommand, (sender, e) => {
Console.WriteLine("我回调了!");
}));
}
public void hideWindow()
{
this.Hide();
}
//调用python模块和代码
private void Button_Click(object sender, RoutedEventArgs e)
{
// 执行 Python 代码
PythonInterpreter.Execute("print('Hello from Python!')");
// 导入 math 模块并调用函数
dynamic math = PythonInterpreter.ImportModule("math");
double result = math.sin(1.0);
Console.WriteLine($"sin(1) = {result}");
}
//调用python文件下面的函数
private void Button_Click_add(object sender, RoutedEventArgs e)
{
// 执行 Python 代码
PythonInterpreter.Execute("print('Hello from Python!')");
// 使用第三方库
using (Py.GIL())
{
// 导入你的Python脚本模块
dynamic TModule = Py.Import("TModule");
// 调用Python函数
int result = TModule.add(2,3);
// 打印结果
Console.WriteLine("和为: " + result);
}
}
//减法
private void Button_Click_sub(object sender, RoutedEventArgs e)
{
// 执行 Python 代码
PythonInterpreter.Execute("print('Hello from Python!')");
// 使用第三方库
using (Py.GIL())
{
// 导入你的Python脚本模块
dynamic TModule = Py.Import("TModule");
// 调用Python函数
int result = TModule.sub(2, 3);
// 打印结果
Console.WriteLine("差为: " + result);
}
}
private void Button_Click_mul(object sender, RoutedEventArgs e)
{
// 执行 Python 代码
PythonInterpreter.Execute("print('Hello from Python!')");
// 使用第三方库
using (Py.GIL())
{
// 导入你的Python脚本模块
dynamic TModule = Py.Import("TModule");
// 调用Python函数
int result = TModule.mul(2, 3);
// 打印结果
Console.WriteLine("积为: " + result);
}
}
private void Button_Click_my_package(object sender, RoutedEventArgs e)
{
// 执行 Python 代码
PythonInterpreter.Execute("print('whl包!')");
// 导入你的Python脚本模块
dynamic TModule = PythonInterpreter.ImportModule("test_package.TModule");
// 调用Python函数
int result = TModule.mul(2, 3);
// 打印结果
Console.WriteLine("商为: " + result);
String main = TModule.main();
// 打印结果
Console.WriteLine("main: " + main);
}
}
}
ok,就可以调用python的这个脚本了,我们也可以打包成.whl包或者cpython 模块包。打.whl我们有一篇文章:Python 中setuptool打包