2013-05-15 19 views
5

Ich verwende ein Python-Skript, um einen Prozess mit subprocess.Popen auszuführen und gleichzeitig die Ausgabe in einer Textdatei zu speichern und auf der Konsole auszugeben. Dies ist mein Code:Ausgabe eines Prozesses zur Laufzeit

result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 
for line in result.stdout.readlines(): #read and store result in log file 
    openfile.write("%s\n" %line) 
    print("%s" %line) 

Above Code funktioniert gut, aber was es tut, ist es zuerst den Prozess abgeschlossen ist und speichert die Ausgabe in Ergebnis variabel. Danach speichert für Schleife die Ausgabe sowie es drucken.

Aber ich möchte die Ausgabe zur Laufzeit (wie mein Prozess kann Stunden dauern, ich bekomme keine Ausgabe für alle diese Stunden).

So gibt es irgendeine andere Funktion, die mir die Ausgabe dynamisch gibt (zur Laufzeit), bedeutet, sobald der Prozess erste Zeile gibt, sollte es gedruckt werden.

+1

Ich habe noch nie wirklich versucht, aber ich glaube, Sie sollen Ihre eigenen schicken Python 'file' Objekt zum' stdout' (oder 'stdin' oder' stderr') Argument. Dann müssen Sie diese Datei abfragen. 'Subprocess' wurde erfunden, um Ihnen diesen Schmerz zu ersparen, aber es scheint, als hätten Sie keine Wahl. Viel Glück. –

+1

_ "es beendet zuerst den Prozess und speichert die Ausgabe in Ergebnis" _ - das ist einfach nicht wahr. – Eric

+0

"Zuerst wird der Prozess abgeschlossen und die Ausgabe im Ergebnis gespeichert" - das stimmt einfach nicht. Nun, wenn ich Popen-Befehl ausführe, läuft es weiter, bis der Prozess beendet ist und dann führt es weitere Codierung aus. Wenn es anders geht, bin ich gespannt darauf. – Niyojan

Antwort

5

Das Problem hier ist, dass bekommt die gesamte Ausgabe vor der Rückkehr, wie es eine vollständige Liste erstellt. direkt iterieren einfach:

for line in result.stdout: 
    print line 
+1

Hinweis: ['für Zeile im Ergebnis.stdout gibt keine Zeilen in "Echtzeit" auf Python 2 zurück, stattdessen "für Zeile in iter (result.stdout.readline, b '')" (http://ideone.com/8KFawl) (Ihr 'print line 'Aussage schlägt vor, dass Sie erwarten, dass es auf Python 2 funktioniert. [Auf Python 3 funktioniert es gut] (http://ideone.com/EUpeGV) – jfs

+0

Ja, es funktioniert, ich werde in Echtzeit ausgegeben, Danke. – Niyojan

1

Sie können über die Zeilen eine nach der anderen durch iterieren readline auf dem Rohr unter Verwendung von:

while True: 
    line = result.stdout.readline() 
    print line.strip() 
    if not line: 
     break 

Die Linien enthalten eine nachlauf \n, die ich für den Druck gestrippt. Wenn der Prozess beendet wird, gibt readline eine leere Zeichenfolge zurück, sodass Sie wissen, wann Sie anhalten müssen.

+1

Es tut mir leid, aber du hast meine Frage nicht bekommen. Was Sie vorgeschlagen haben, ich beende es bereits mit for-Schleife, was ich will ist Zeile für Zeile ausgegeben, während der Prozess noch im laufenden Zustand ist. – Niyojan

+1

hast du es versucht? Sie verwenden 'readlines', das alle Zeilen zurückgibt. Das ist nur nach Kündigung möglich. Mit 'readline' erhalten Sie nur die nächsten –

+0

result.stdout funktioniert gut für mich, aber Ihre line.strip() -Funktionen ist hilfreich, da ich zu viele" b '\ r \ n' "davor bekam, Danke – Niyojan

3

.readlines() gibt eine Liste von alle die Linien der Prozess zurück, während offen, das heißt, er nichts zurück, bis alle Ausgabe vom subprocess empfangen wird. Um Zeile für Zeile in „Echtzeit“ zu lesen:

import sys 
from subprocess import Popen, PIPE 

proc = Popen(cmd, shell=True, bufsize=1, stdout=PIPE) 
for line in proc.stdout: 
    openfile.write(line) 
    sys.stdout.buffer.write(line) 
    sys.stdout.buffer.flush() 
proc.stdout.close() 
proc.wait() 

Hinweis: Wenn der Unterprozess verwendet Block-Buffering, wenn es in nicht-interaktiven Modus ausgeführt wird; Möglicherweise benötigen Sie pexpect, pty modules oder stdbuf, unbuffer, script commands.

Hinweis: auf Python 2, könnten Sie auch iter() verwenden müssen, „Echtzeit“ Ausgabe zu erhalten:

for line in iter(proc.stdout.readline, ""): 
    openfile.write(line) 
    print line, 
Verwandte Themen