2009-08-14 7 views
4

Ich habe einige Befehle, die ich mit dem Subprozess-Modul laufen. Ich möchte dann die Zeilen der Ausgabe durchlaufen. Die Dokumentation sagt, dass man data_stream.stdout.read nicht tut, was ich nicht bin, aber ich kann etwas tun, was das anruft. Ich Looping über die Ausgabe wie folgt aus:Python Subprozess-Modul: Schleife über stdout von Kind-Prozess

for line in data_stream.stdout: 
    #do stuff here 
    . 
    . 
    . 

kann dies zu Deadlocks wie aus data_stream.stdout lesen oder sind die Popen Module für diese Art von looping so eingerichtet, dass sie den Code kommuniziert aber alle callings Griffe davon für dich?

Antwort

6

Sie müssen sich Gedanken über Deadlocks machen, wenn Sie mit Ihrem Subprozess kommunizieren, d. H., Wenn Sie auf stdin schreiben und von stdout lesen. Da diese Rohre im Cache gespeichert werden können, ist zu tun, diese Art von Zwei-Wege-Kommunikation sehr viel ein no-no:

data_stream = Popen(mycmd, stdin=PIPE, stdout=PIPE) 
data_stream.stdin.write("do something\n") 
for line in data_stream: 
    ... # BAD! 

Wenn Sie jedoch nicht eingerichtet haben stdin (oder stderr), wenn data_stream konstruieren, sollten Sie gut.

data_stream = Popen(mycmd, stdout=PIPE) 
for line in data_stream.stdout: 
    ... # Fine 

Wenn Sie eine bidirektionale Kommunikation benötigen, verwenden Sie communicate.

+0

Fast richtig, aber, wie die Dokumentation über 'kommunizieren 'sagt," Die gelesenen Daten werden im Speicher zwischengespeichert, also verwenden Sie diese Methode nicht, wenn die Datengröße groß oder unbegrenzt ist. " –

+0

Also, wenn ich nie mit Stderr oder Stdin als Schleifen in dieser Mode ist in Ordnung. – Matt

0

data_stream.stdout ist eine Standardausgabe Griff. Sie sollten nicht darüber schleifen. communicate gibt Tupel von (stdoutdata, stderr) zurück. diese stdoutdata sollten Sie verwenden, um Ihre Sachen zu tun.

3

Die Antworten von SilentGhost/chrispy sind in Ordnung, wenn Sie eine geringe bis mäßige Ausgabe von Ihrem Subprozess haben. Manchmal gibt es jedoch eine Menge Ausgaben - zu viel, um bequem im Speicher zu puffern. In einem solchen Fall ist die Sache zu tun start() der Prozess, und spawnen Sie ein paar Threads - eins zu lesen child.stdout und eins zu lesen child.stderr wo child ist der Subprozess. Sie müssen dann wait() für den Unterprozess zu beenden.

Dies ist tatsächlich, wie communicate() funktioniert; Der Vorteil der Verwendung eigener Threads besteht darin, dass Sie die Ausgabe des Subprozesses so verarbeiten können, wie er generiert wird. Zum Beispiel verwende ich in meinem Projekt python-gnupg diese Technik, um die Statusausgabe von der ausführbaren GnuPG-Datei zu lesen, anstatt auf alles zu warten, indem ich communicate() aufruft. Sie können gerne die Quelle dieses Projektes einsehen - das entsprechende Zeug befindet sich im Modul gnupg.py.

+1

FYI, 'communicate()' erstellt keine neuen Threads, sondern verwendet 'select()' oder 'poll()' in POSIX. – musiphil

6

Die beiden Antworten haben den Kern des Problems ziemlich gut erfasst: mischen Sie nicht etwas mit dem Subprozess, lesen etwas davon, schreiben wieder usw. - die Pufferung der Pipe bedeutet, dass Sie das Risiko eines Deadlocks haben . Wenn Sie können, schreiben Sie alles, was Sie brauchen, um in den Subprozess FIRST zu schreiben, schließen Sie die Pipe und lesen Sie dann DANN alles, was der Subprozess zu sagen hat; communicate ist nett für den Zweck, wenn die Datenmenge nicht zu groß ist, um in den Speicher zu passen (wenn es ist, können Sie immer noch den gleichen Effekt "manuell" erreichen).

Wenn Sie eine feinkörnigere Interaktion benötigen, suchen Sie stattdessen nach pexpect oder, wenn Sie unter Windows arbeiten, wexpect.