web-dev-qa-db-fra.com

Comment exécuter un script Python à partir de C #?

Ce type de question a déjà été posé à des degrés divers, mais j'estime qu'il n'a pas été répondu de manière concise et je le pose à nouveau.

Je veux exécuter un script en Python. Disons que c'est ça:

if __== '__main__':
    with open(sys.argv[1], 'r') as f:
        s = f.read()
    print s

Qui obtient un emplacement de fichier, le lit, puis imprime son contenu. Pas si compliqué.

Bon, alors comment puis-je l'exécuter en C #?

Voici ce que j'ai maintenant:

    private void run_cmd(string cmd, string args)
    {
        ProcessStartInfo start = new ProcessStartInfo();
        start.FileName = cmd;
        start.Arguments = args;
        start.UseShellExecute = false;
        start.RedirectStandardOutput = true;
        using (Process process = Process.Start(start))
        {
            using (StreamReader reader = process.StandardOutput)
            {
                string result = reader.ReadToEnd();
                Console.Write(result);
            }
        }
    }

Lorsque je passe l'emplacement code.py en tant que cmd et l'emplacement filename en tant que args, cela ne fonctionne pas. On m'a dit que je devrais passer python.exe en tant que cmd, puis code.py filename en tant que args.

Je cherche depuis un moment et je ne trouve que des personnes qui suggèrent d’utiliser IronPython ou autre. Mais il doit y avoir un moyen d'appeler un script Python à partir de C #.

Quelques précisions:

Je dois l'exécuter à partir de C #, je dois capturer la sortie et je ne peux pas utiliser IronPython ou quoi que ce soit d'autre. Quel que soit le hack que vous avez, tout ira bien.

P.S .: Le code Python que j’exécute est beaucoup plus complexe que cela. Il renvoie la sortie dont j’ai besoin en C # et le code C # appelle constamment le Python.

Imagine que c'est mon code:

    private void get_vals()
    {
        for (int i = 0; i < 100; i++)
        {
            run_cmd("code.py", i);
        }
    }
97
Inbar Rose

Cela ne fonctionne pas parce que vous avez UseShellExecute = false.

Si vous n'utilisez pas le shell, vous devrez fournir le chemin complet de l'exécutable python sous la forme FileName et créer la chaîne Arguments pour fournir à la fois votre script et le fichier que vous souhaitez lire.

Notez également que vous ne pouvez pas RedirectStandardOutput si UseShellExecute = false.

Je ne sais pas trop comment la chaîne d'argument doit être formatée pour Python, mais vous aurez besoin de quelque chose comme ça:

private void run_cmd(string cmd, string args)
{
     ProcessStartInfo start = new ProcessStartInfo();
     start.FileName = "my/full/path/to/python.exe";
     start.Arguments = string.Format("{0} {1}", cmd, args);
     start.UseShellExecute = false;
     start.RedirectStandardOutput = true;
     using(Process process = Process.Start(start))
     {
         using(StreamReader reader = process.StandardOutput)
         {
             string result = reader.ReadToEnd();
             Console.Write(result);
         }
     }
}
91
Master Morality

Si vous souhaitez utiliser IronPython, vous pouvez exécuter des scripts directement en C #:

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

private static void doPython()
{
    ScriptEngine engine = Python.CreateEngine();
    engine.ExecuteFile(@"test.py");
}

Obtenez IronPython ici.

49
Chris Dunaway

Exécuter le script Python à partir de C

Créez un projet C # et écrivez le code suivant.

using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            run_cmd();
        }

        private void run_cmd()
        {

            string fileName = @"C:\sample_script.py";

            Process p = new Process();
            p.StartInfo = new ProcessStartInfo(@"C:\Python27\python.exe", fileName)
            {
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };
            p.Start();

            string output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();

            Console.WriteLine(output);

            Console.ReadLine();

        }
    }
}

Python sample_script

print "Test Python C #"

Vous verrez le'Test Python C #'dans la console de C #.

22
Rohit Salunke

J'ai rencontré le même problème et la réponse de Maître Moralité ne l'a pas fait pour moi. Ce qui suit, qui est basé sur la réponse précédente, a fonctionné:

private void run_cmd(string cmd, string args)
{
 ProcessStartInfo start = new ProcessStartInfo();
 start.FileName = cmd;//cmd is full path to python.exe
 start.Arguments = args;//args is path to .py file and any cmd line args
 start.UseShellExecute = false;
 start.RedirectStandardOutput = true;
 using(Process process = Process.Start(start))
 {
     using(StreamReader reader = process.StandardOutput)
     {
         string result = reader.ReadToEnd();
         Console.Write(result);
     }
 }
}

Par exemple, cmd serait @C:/Python26/python.exe et args serait C://Python26//test.py 100 si vous voulez exécuter test.py avec l'argument de ligne cmd 100. Notez que le chemin du fichier .py ne contient pas le symbole @.

10
Derek

Juste pour attirer votre attention sur ceci:

https://code.msdn.Microsoft.com/windowsdesktop/C-and-Python-interprocess-171378ee

Cela fonctionne très bien.

2
cs0815

En fait, il est très facile d’intégrer Csharp (VS) à Python avec IronPython. Ce n'est pas si complexe ... Comme Chris Dunaway l'a déjà dit dans la section réponse, j'ai commencé à construire cette intégration pour mon propre projet. N c'est assez simple. Suivez simplement ces étapes pour obtenir vos résultats.

étape 1: Ouvrez VS et créez un nouveau projet ConsoleApp vide.

étape 2: Aller aux outils -> Gestionnaire de paquets NuGet -> Console du gestionnaire de paquets.

étape 3: Après cela, ouvrez ce lien dans votre navigateur et copiez la commande NuGet. Lien: https://www.nuget.org/packages/IronPython/2.7.9

étape 4: Après avoir ouvert le lien ci-dessus, copiez PM> Install-Package IronPython-Version 2.7.9 commande et collez-le dans la console NuGet sous VS . Il installera les packages de support.

étape 5: C’est mon code que j’ai utilisé pour exécuter un fichier .py stocké dans mon fichier Python.exe annuaire.

using IronPython.Hosting;//for DLHE
using Microsoft.Scripting.Hosting;//provides scripting abilities comparable to batch files
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
class Hi
{
private static void Main(string []args)
{
Process process = new Process(); //to make a process call
ScriptEngine engine = Python.CreateEngine(); //For Engine to initiate the script
engine.ExecuteFile(@"C:\Users\daulmalik\AppData\Local\Programs\Python\Python37\p1.py");//Path of my .py file that I would like to see running in console after running my .cs file from VS.//process.StandardInput.Flush();
process.StandardInput.Close();//to close
process.WaitForExit();//to hold the process i.e. cmd screen as output
}
} 

étape 6: sauvegarder et exécuter le code 

0
Daulmalik

J'ai des problèmes avec stdin/stout - lorsque la taille de la charge utile dépasse plusieurs kilo-octets, elle se bloque. Je dois appeler les fonctions Python non seulement avec des arguments courts, mais également avec une charge utile personnalisée qui pourrait être volumineuse.

Il y a quelque temps, j'ai écrit une bibliothèque d'acteurs virtuels qui permet de distribuer des tâches sur différentes machines via Redis. Pour appeler du code Python, j'ai ajouté une fonctionnalité permettant d'écouter les messages de Python, de les traiter et de renvoyer les résultats au format .NET. Voici une brève description de son fonctionnement .

Cela fonctionne également sur une seule machine, mais nécessite une instance Redis. Redis ajoute certaines garanties de fiabilité: la charge utile est stockée jusqu'à ce qu'un ouvrier accuse réception. Si un travail meurt, la charge utile est renvoyée dans une file d'attente de travaux, puis est retraitée par un autre ouvrier.

0
V.B.

Définissez WorkingDirectory ou spécifiez le chemin d'accès complet du script python dans l'argument

ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
//start.WorkingDirectory = @"D:\script";
start.Arguments = string.Format("D:\\script\\test.py -a {0} -b {1} ", "some param", "some other param");
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
    using (StreamReader reader = process.StandardOutput)
    {
        string result = reader.ReadToEnd();
        Console.Write(result);
    }
}
0
LIU YUE