如何从C#应用程序调用(Iron)Python代码?

66

有没有一种方法可以从 C# 调用 Python 代码,使用 IronPython 假设呢?如果可以,怎样做呢?


4
C# 4.0中有一个重要的关键字,叫做dynamic。你知道它吗?很重要。 - Hans Passant
https://dev59.com/gs77oIgBc1ULPQZFGW3y#75983934 - Mucahid Uslu
3个回答

133
在C#/.NET 4应用程序中,特别是通过使用 dynamic 类型来改善对动态语言的支持后,该过程变得简单。但它最终取决于您打算如何在应用程序中使用(Iron)Python代码。您始终可以作为单独的进程运行 ipy.exe 并传入源文件以便执行。但您可能想要将它们托管在您的C#应用程序中。这会留下许多选项。
  1. 添加对 IronPython.dllMicrosoft.Scripting.dll 程序集的引用。通常您可以在根 IronPython 安装目录中找到它们。

  2. 在源代码顶部添加 using IronPython.Hosting; 并使用 Python.CreateEngine() 创建 IronPython 脚本引擎实例。

  3. 从这里您有几个选择,但基本上您将创建一个 ScriptScopeScriptSource 并将其存储为 dynamic 变量。这使您可以在必要时从C#执行或操作作用域。

选项1:

使用 CreateScope() 创建一个空的 ScriptScope,直接在 C# 代码中使用,但在 Python 源中也可用。你可以将这些看作解释器实例中的全局变量。

dynamic scope = engine.CreateScope();
scope.Add = new Func<int, int, int>((x, y) => x + y);
Console.WriteLine(scope.Add(2, 3)); // prints 5

选项2:

使用Execute()来执行任何IronPython代码字符串。您可以使用其中的一种重载,在其中可以传递一个ScriptScope来存储或使用在代码中定义的变量。

var theScript = @"def PrintMessage():
    print 'This is a message!'

PrintMessage()
";

// execute the script
engine.Execute(theScript);

// execute and store variables in scope
engine.Execute(@"print Add(2, 3)", scope);
// uses the `Add()` function as defined earlier in the scope

选项3:

使用ExecuteFile()来执行一个IronPython源文件。你可以使用重载,其中您可以传递一个ScriptScope来存储或使用在代码中定义的变量。

// execute the script
engine.ExecuteFile(@"C:\path\to\script.py");

// execute and store variables in scope
engine.ExecuteFile(@"C:\path\to\script.py", scope);
// variables and functions defined in the scrip are added to the scope
scope.SomeFunction();

选项4:

使用GetBuiltinModule()函数或ImportModule()扩展方法创建一个作用域,其中包含所述模块中定义的变量。以这种方式导入的模块必须设置在搜索路径中。

dynamic builtin = engine.GetBuiltinModule();
// you can store variables if you want
dynamic list = builtin.list;
dynamic itertools = engine.ImportModule("itertools");
var numbers = new[] { 1, 1, 2, 3, 6, 2, 2 };
Console.WriteLine(builtin.str(list(itertools.chain(numbers, "foobar"))));
// prints `[1, 1, 2, 3, 6, 2, 2, 'f', 'o', 'o', 'b', 'a', 'r']`

// to add to the search paths
var searchPaths = engine.GetSearchPaths();
searchPaths.Add(@"C:\path\to\modules");
engine.SetSearchPaths(searchPaths);

// import the module
dynamic myModule = engine.ImportModule("mymodule");

在.NET项目中托管Python代码可以实现很多功能。 C#可以帮助更轻松地解决这些差异。结合这里提到的所有选项,您几乎可以做任何想做的事情。当然,在IronPython.Hosting命名空间中找到的类中还有更多的操作,但这应该足以让您入门。


7
需要使用Python.CreateEngine()引擎。 - schoetbi

11

要运行一个函数,你不能像Jeff Mercado的第3个选项那样调用它(这是一个非常好和有帮助的选项!但至少在.NET 4.5上,这个选项无法编译)。你可以使用ScriptScope.GetVariable来获取实际的函数,然后就可以像调用C#函数一样调用它了。

C#代码:

var var1,var2=...
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
engine.ExecuteFile(@"C:\test.py", scope);
dynamic testFunction = scope.GetVariable("test_func");
var result = testFunction(var1,var2);

Python代码:

def test_func(var1,var2):
    ...do something...
花了我一段时间才最终弄明白,其实很简单...只可惜没有好的IronPython文档。希望这可以帮到你 :)

花了我一段时间才最终弄明白,其实很简单..只可惜没有好的IronPython文档。希望这可以帮到你 :)


7

1) 需要安装

Install-Package DynamicLanguageRuntime -Version 1.2.2

2) 需要使用以下方法添加 "Iropython.dll": https://www.webucator.com/how-to/how-add-references-your-visual-studio-project.cfm

3) 需要使用:

using IronPython.Hosting;
using IronPython.Runtime;
using IronPython;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting;

3) 需要设置变量

ScriptEngine engine = Python.CreateEngine();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接