在.Net6中调用IronPython实现动态执行脚本
本文显示了一个在.Net6中借用IronPython动态执行Python脚本的功能的简单示例,可供需要动态执行脚本的工况进行参考。示例显示了动态Python脚本能与c#代码交互,支持定义函数,定义变量,获取返回值(“不需特殊处理”)等功能。
开发环境及相关依赖需求
- 依赖Nuget包:IronPython V3.4.1;
- 运行时:.Net6.0 (其他环境未测试);
代码
// Program.cs
namespace ConsoleOutValue
{
internal class Program
{
static void Main(string[] args)
{
CSPython cspy = new CSPython();
cspy.Test1();
Console.ReadLine();
}
}
}
// CSPython.cs
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
namespace ConsoleOutValue
{
public class CSPython
{
private ScriptEngine engine;
private ScriptScope scope;
public CSPython()
{
// 创建 IronPython 引擎实例
engine = Python.CreateEngine();
scope = engine.CreateScope();
}
public void DoAction(string? exp, ScriptScope scope)
{
if (string.IsNullOrWhiteSpace(exp)) return; try
{
dynamic result = engine.Execute(exp, scope);
Console.WriteLine($" 执行结果:{exp}={result}");
}
catch (Exception ex)
{
Console.WriteLine(" 执行结果:" + ex.Message);
}
}
public void DoActionNewScope(string? exp)
{
var scope = engine.CreateScope();
engine.Execute("import math", scope);
DoAction(exp, scope);
}
public void Test1()
{
Console.WriteLine("已经导入math;使用方法:\n math.sin(60/180*3.1415926)\n");
engine.Execute("import math", scope);
engine.Execute("def myadd(a, b):\n return a + b", scope); // 在 IronPython 中定义函数
DoAction("math.sin(60)", scope);
DoActionNewScope("math.sin(60/180*3.1415926)");
var script = engine.CreateScriptSourceFromString("myadd(2, 3)"); // 调用函数
dynamic result = script.Execute(scope); // 执行 IronPython 代码并获取结果
int sum = result;
Console.WriteLine($" 执行结果:myadd(2, 3)={sum}");
string exp = "999**9";
dynamic result2 = engine.Execute(exp);
Console.WriteLine($" 执行结果:{exp}={result2}");
while (true)
{
DoAction(Console.ReadLine(), scope);
}
}
}
}
执行情况
# 基本测试
已经导入math;使用方法:
math.sin(60/180*3.1415926)
执行结果:math.sin(60)=-0.3048106211022167 # 调用math库函数
执行结果:math.sin(60/180*3.1415926)=0.8660253948528063 # 调用math库函数
执行结果:myadd(2, 3)=5 # 调用Python自定义函数
执行结果:999**9=991035916125874083964008999 # 直接计算表达式
# 定义变量及使用
a=666 # 定义变量
执行结果:a=666=
a+111 # 使用变量
执行结果:a+111=777
a+myadd(111,111) # 使用变量及自定义函数
执行结果:a+myadd(111,111)=888
def myadd2(a,b): return a+b # 定义函数myadd2
执行结果:def myadd2(a,b): return a+b=
a+myadd2(1,0) # 使用尴尬定义的函数myadd2
执行结果:a+myadd2(1,0)=667
dasdda+dasd # 执行错误代码
执行结果:name 'dasdda' is not defined
概念及个人理解
- ScriptScope 作用域,类似与命名空间,只有同一Scope下导入的模块或定义的函数才能被调用
- ScriptSource 脚本代码,可从文件加载,或直接由用户输入
- ScriptEngine 脚本引擎,相当于CPU
文档
- 官方文档:IronPython。
- 个人保存及中文翻译:见资源绑定(支持中英双语同时显示)。