2010-02-23 6 views
1

J'ai écrit un programme simple qui capture et exécute des scripts Python en ligne de commande, mais il y a un problème. Le texte passé à une fonction d'entrée Python n'est pas écrit dans mon programme malgré la capture de mon programme stdout.Certaines commandes Python ne sont pas interceptées dans Stdout

Par exemple: Le script Python:

import sys 

print("Hello, World!") 
x = input("Please enter a number: ") 
print(x) 

print("This work?") 

écrirait "Bonjour, monde!" puis arrêtez. Quand je lui passe un numéro, il continue à écrire "S'il vous plaît entrer un nombre: 3". Que se passe-t-il? Des solutions? Mon C# est la suivante:

public partial class PyCon : Window 
{ 
     public string strPythonPath; 
     public string strFile; 
     public string strArguments; 
     private StreamWriter sw; 

     public PyCon(string pythonpath, string file, string args) 
     { 
      strPythonPath = pythonpath; 
      strFile = file; 
      strArguments = args; 

      InitializeComponent(); 

      Process p = new Process(); 

      p.StartInfo.FileName = strPythonPath; 
      p.StartInfo.Arguments = "\"" + strFile + "\" " + strArguments; 

      p.StartInfo.UseShellExecute = false; 
      p.StartInfo.CreateNoWindow = true; 

      p.StartInfo.RedirectStandardInput = true; 
      p.StartInfo.RedirectStandardOutput = true; 
      p.StartInfo.RedirectStandardError = true; 

      p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived); 
      p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived); 

      p.Start(); 
      p.BeginOutputReadLine(); 
      p.BeginErrorReadLine(); 
      sw = p.StandardInput; 
     } 

     private void p_OutputDataReceived(object sendingProcess, DataReceivedEventArgs received) { 
      if (!String.IsNullOrEmpty(received.Data)) { 
       AppendConsole(received.Data); 
      } 
     } 

     private void p_ErrorDataReceived(object sendingProcess, DataReceivedEventArgs received) { 
      if (!String.IsNullOrEmpty(received.Data)) { 
       AppendConsole(received.Data); 
      } 
     } 

     private void AppendConsole(string message) { 
      if (!txtConsole.Dispatcher.CheckAccess()) { 
       txtConsole.Dispatcher.Invoke(DispatcherPriority.Normal, (System.Windows.Forms.MethodInvoker)delegate() { txtConsole.AppendText(message + "\n"); }); 
      } else { 
       //Format text 
       message = message.Replace("\n", Environment.NewLine); 

       txtConsole.AppendText(message + "\n"); 
      } 
     } 

     private void txtInput_KeyUp(object sender, KeyEventArgs e) { 
      if (e.Key != Key.Enter) return; 

      sw.WriteLine(txtInput.Text); 

      txtInput.Text = ""; 


     } 
    } 

Edit: Après beaucoup de recherches et l'aide de ce fil, je suis venu à la conclusion que le problème est avec la commande d'entrée Python ne pas appeler la C# DataReceivedEventHandler. Il n'y a peut-être pas de solution à cela en plus des changements de script. Si tel est le cas, je vais faire la réponse contenant ces changements comme acceptés. Merci pour l'aide les gars!

Répondre

1

Des odeurs semblables à l'E/S Python sont mises en mémoire tampon, c'est-à-dire attendent un CRLF puis envoient une ligne entière à la fois. Vous pouvez essayer de transformer cette off (python -u myscript.py, ou définir la variable d'environnement PYTHONUNBUFFERED) ou le travail autour de lui avec quelque chose comme ceci:

print("Hello, World!") 
print("Please enter a number: ") 
x = input() 
print(x) 
+0

La solution de contournement de script est géniale. Cela corrige le problème, mais ce n'est pas idéal. La définition de PYTHONUNBUFFERED ou l'exécution du script avec -u ne semblent pas corriger le problème. –

1

Il est difficile de dire parce que je suis à l'aide python 2.6 et vous semblent utiliser 3.x, et je n'ai pas non plus programmé en C# pour un bon moment mais je pense que cette ligne:

sw.WriteLine(txtInput.Text); 

envoie « 3 » plus une fenêtre caractère de nouvelle ligne.

Essayez:

sw.Write(txtInput.Text + "\n") 
sw.Flush() 

Cela, envoyez simplement un newline normal au lieu d'un retour chariot de fenêtres qui peut être la question. Assurez-vous de toujours rincer lorsque vous traitez une communication de flux compliquée comme celle-ci!

Encore une chose, assurez-vous que vous pouvez simplement rediriger cela à l'invite de commande. Trop souvent, les programmeurs essaient de tout faire en même temps et de se coincer:

./stdintest.py < input.txt 

Si elle le fait, ça marche pas, il ne va pas travailler en C#. Bonne chance

+0

Comme une note, si je suis allé dans input.txt et au lieu de mettre un saut de ligne normal, mettre un^M (caractère windows) après le 3, python 2.6 lancerait une exception "EOF inattendu lors de l'analyse". Cela peut ou peut ne pas être le cas dans python 3.x – manifest

+0

Flushing the StreamWriter est certainement un bon appel. La chose de nouvelle ligne traite cependant essentiellement le problème opposé que j'ai. Les entrées sont correctes, mais la chaîne transmise à la commande d'entrée Python n'apparaît pas dans mes données capturées. Donc, exécuter le programme va quelque chose comme ceci: Bonjour, monde! 3 [<-I tapez ceci et il est publié sur StreamWriter] Veuillez entrer un nombre: 3 Cette œuvre? Je pense que crazyscot aboyait le bon arbre. –

+0

Je suis passé à la version 2.6. Je vois l'erreur à laquelle vous faisiez référence. Cela ne semble pas être un problème dans 3.1. –

Questions connexes