web-dev-qa-db-fra.com

Comment puis-je appeler du code Python (Iron) à partir d'une application C #?

Existe-t-il un moyen d'appeler Python, en utilisant IronPython je suppose, à partir de C #? Si oui, comment?

51
David Thielen

Le processus est simple, en particulier dans une application C # /. NET 4 où la prise en charge des langages dynamiques a été améliorée via l'utilisation du type dynamic. Mais tout dépend en fin de compte de la façon dont vous avez l'intention d'utiliser le code (Iron) Python dans votre application. Vous pouvez toujours exécuter ipy.exe En tant que processus séparé et transmettre vos fichiers source afin qu'ils puissent être exécutés. Mais vous vouliez probablement Host eux dans votre application C #. Cela vous laisse de nombreuses options.

  1. Ajoutez une référence aux assemblages IronPython.dll Et Microsoft.Scripting.dll. Vous les trouverez généralement dans votre répertoire d'installation IronPython racine.

  2. Ajoutez using IronPython.Hosting; En haut de votre source et créez une instance du moteur de script IronPython à l'aide de Python.CreateEngine().

  3. Vous avez quelques options à partir d'ici, mais en gros, vous créez un ScriptScope ou ScriptSource et le stockez en tant que variable dynamic. Cela vous permet de l'exécuter ou de manipuler les étendues à partir de C # si vous choisissez de le faire.

Option 1:

Utiliser CreateScope() pour créer un ScriptScope vide à utiliser directement dans le code C # mais utilisable dans les sources Python. Vous pouvez les considérer comme vos variables globales dans un exemple de l'interprète.

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

Option 2:

Utilisation de Execute() pour exécuter n'importe quel code IronPython dans une chaîne. Vous pouvez utiliser la surcharge où vous pouvez passer dans un ScriptScope pour stocker ou utiliser des variables définies dans le code.

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

Option 3:

Utilisation de ExecuteFile() pour exécuter un fichier source IronPython. Vous pouvez utiliser la surcharge où vous pouvez passer dans un ScriptScope pour stocker ou utiliser des variables définies dans le code.

// 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();

Option 4:

Utiliser GetBuiltinModule() ou la méthode d'extension ImportModule() pour créer un scope contenant les variables définies dans ledit module. Les modules importés de cette façon doivent être définis dans les chemins de recherche.

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");

Vous pouvez faire beaucoup d'hébergement Python dans vos projets .NET. C # aide à combler cet écart plus facilement à traiter. En combinant toutes les options mentionnées ici, vous pouvez faire à peu près tout ce que vous voulez. Il y a bien sûr plus à faire avec les classes trouvées dans l'espace de noms IronPython.Hosting, Mais cela devrait être plus que suffisant pour vous aider à démarrer.

112
Jeff Mercado

Pour exécuter une fonction, vous ne pouvez pas l'appeler comme dans l'option 3 de la réponse de Jeff Mercado (qui est excellente et très utile! Mais cette option ne se compile pas, au moins sur .NET 4.5). Vous pouvez utiliser ScriptScope.GetVariable pour obtenir la fonction réelle, puis vous pouvez l'appeler comme une fonction C #. Utilisez-le comme ceci:

Code 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);

Code Python:

def test_func(var1,var2):
    ...do something...

Cela m'a pris un certain temps pour finalement comprendre, et c'est assez simple .. Dommage qu'il n'y ait pas de bonne documentation IronPython. J'espère que cela t'aides :)

3
LiRoN