Подтвердить что ты не робот

Как я могу вызвать (Iron) код Python из приложения С#?

Есть ли способ вызвать код Python, используя, предположительно, IronPython, из С#? Если да, то как?

4b9b3361

Ответ 1

Процесс прост, особенно в приложении С#/.NET 4, где поддержка динамических языков улучшена с использованием типа dynamic. Но все это в конечном итоге зависит от того, как вы собираетесь использовать (Iron) код Python в своем приложении. Вы всегда можете запустить ipy.exe как отдельный процесс и передать исходные файлы, чтобы они могли быть выполнены. Но вы, вероятно, захотели разместить их в своем приложении С#. Это оставляет вам много вариантов.

  • Добавьте ссылку на сборки IronPython.dll и Microsoft.Scripting.dll. Обычно вы найдете их в корневом каталоге установки IronPython.

  • Добавьте using IronPython.Hosting; в начало вашего источника и создайте экземпляр механизма сценариев IronPython с помощью Python.CreateEngine().

  • У вас есть пара вариантов, но в основном вы создадите ScriptScope или ScriptSource и сохраните его как переменную dynamic. Это позволяет выполнить его или управлять областями из С#, если вы решите это сделать.

Вариант 1:

Использование CreateScope() для создания пустого ScriptScope для непосредственного использования кода С#, но используемого в источниках 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. С# помогает преодолеть этот пробел, с которым легче справиться. Объединив все варианты, упомянутые здесь, вы можете сделать практически все, что захотите. Конечно, вы можете сделать больше с классами, найденными в пространстве имен IronPython.Hosting, но этого должно быть более чем достаточно, чтобы вы начали.

Ответ 2

Чтобы запустить функцию, вы не можете называть ее, как в Варианте 3 ответа Джеффа Меркадо (что очень полезно и полезно! Но этот параметр не компилируется, по крайней мере, на.NET 4.5). Вы можете использовать ScriptScope.GetVariable для получения фактической функции, а затем вы можете назвать ее как функцию С#. Используйте его так:

Код С#:

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. Надеюсь это поможет :)