2016-06-20 6 views
1

Ich versuche, stdout.readline und die Ergebnisse (d. H. Jede Zeile, zum Zeitpunkt des Drucks sie an das Terminal) auf eine multiprocessing.Queue für uns in einer anderen .py-Datei. Doch der Ruf:Python lesen Popen kontinuierlich (Windows)

res = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1) 
with res.stdout: 
    for line in iter(res.stdout.readline, b''): 
     print line 
res.wait() 

blockiert und die Ergebnisse werden nach gedruckt werden der Prozess abgeschlossen ist (oder gar nicht, wenn Exit-Code nicht zurückgegeben wird).

Ich habe SO für Antworten darauf durchsucht, und habe versucht, bufsize = 1, Laichen Threads, die das Lesen behandeln, mit Filedescripts, etc. Keine scheint zu funktionieren. Ich muss vielleicht das Modul pexpect verwenden, aber ich bin mir nicht sicher, wie es noch funktioniert.

Ich habe auch versucht,

def enqueue_output(self, out, queue): 
    for line in iter(out.readline, b''): 
     queue.put([line]) 
    out.close() 

Um die Daten in die Warteschlange gestellt, aber da out.readline zu blockieren scheint, wird das Ergebnis das gleiche sein.

Kurz gesagt: Wie stelle ich die Subprozessausgabe zum Zeitpunkt des Drucks zur Verfügung? Er druckt Stücke von 1-10 Zeilen zu einer Zeit, aber diese mir zurückgegeben werden, wenn der Prozess abgeschlossen ist, aber auch ..

Verwandte durch Zeilenumbrüche getrennt:

Python subprocess readlines() hangs

Python: read streaming input from subprocess.communicate()

Non-blocking read on a subprocess.PIPE in python

+0

Sie müssen herausfinden, ob das Programm über eine Befehlszeilenoption zum Deaktivieren der Pufferung oder zum Verwenden eines interaktiven Modus verfügt, z. B. Pythons Optionen "-u" und "-i". Sonst puffert es höchstwahrscheinlich das Schreiben in seine "stdout", wenn es sieht, dass es eine Pipe ist. Die Ausgabe wird nur in die Pipe geschrieben, wenn der Puffer voll ist oder wenn das Programm den Puffer manuell löscht oder wenn es beendet wird. Python am anderen Ende der Pipe hat keine Kontrolle über dieses Verhalten. – eryksun

+0

Sie erwähnen Pexpect und haben die Frage markiert "Pty", aber Windows hat keine Terminals und Pseudo-Terminals. Pexpect kommt winpexpect am nächsten, verwendet aber Pipes, um das Pufferungsproblem nicht zu lösen. Die korrekte Handhabung in Windows erfordert die Konsolen-API, möglicherweise indem ein Hilfsprogramm an eine fensterlose Konsole angehängt wird, um die Ausgabe des Programms zu lesen und in seine Eingabe zu schreiben.Ich habe kein Python-Modul gesehen, das dies für Windows implementiert. – eryksun

+0

@eryksun Ich entfernte das PTY-Tag. Ich hatte Angst, dass das Problem in dem Prozess liegt, den ich anrufe. Ich werde den zuständigen Entwickler darum bitten müssen. Es scheint einige Probleme bei der Pufferung zu geben, wenn Windows ausgeführt wird und die Subprozess- und Befehlszeilenfunktionen verwendet werden. – enrm

Antwort

1

Wie von @eryksun erklärt und durch Ihren Kommentar bestätigt, ist die Ursache der Pufferung die Verwendung von printf durch die C-Anwendung.

Standardmäßig printf puffert seine Ausgabe, aber die Ausgabe wird auf Newline geleert oder wenn eine Lesung auftritt , wenn die Ausgabe an eine Klemme gerichtet ist. Wenn die Ausgabe an eine Datei oder eine Pipe geleitet wird, tritt die tatsächliche Ausgabe nur auf, wenn der Puffer voll ist.

Glücklicherweise gibt es unter Windows keine Low-Level-Pufferung (*). Das bedeutet, dass das Aufrufen von setvbuf(stdout, NULL, _IONBF, 0); nahe dem Anfang des Programms ausreichend wäre. Aber leider brauchen Sie überhaupt keine Pufferung (_IONBF), da die Zeilenpufferung unter Windows als vollständige Pufferung implementiert ist.

(*) Auf Unix- oder Linux-Systemen kann der zugrunde liegende Systemaufruf eine eigene Pufferung hinzufügen. Das bedeutet, dass ein Programm, das die niedrige Stufe verwendet, unter Windows nicht gepuffert wird, aber weiterhin unter Linux gepuffert wird, wenn die Standardausgabe mit einer Pipe oder einer Datei verbunden ist.

+0

Upvoting für die Bereitstellung relevanter Informationen. Also, um die erste Frage zu beantworten: Es gibt keine Möglichkeit, den Puffer abzurufen, bis der Stream geschlossen ist? – enrm

+0

Genauer gesagt, erhalten Sie von Zeit zu Zeit volle Puffer, bis der Stream geschlossen ist. Aber ohne das aufgerufene Programm zu ändern, kann ich mir keinen Weg vorstellen, diese Pufferung zu vermeiden. –

+0

Haben Sie eine Referenz für das Low-Level-Puffern von Pipes unter Linux oder einem anderen Unix-Betriebssystem? Die Pipe selbst hat einen Puffer, der ihre Kapazität bestimmt, bevor ein "Schreiben" blockiert oder fehlschlägt, aber ein "Schreiben" an einem Ende sollte sofort für ein "Lesen" am anderen Ende verfügbar sein. Bei Windows I/O verwendet der allgemeine Dateizugriff den Systemcache, und Sie müssen die Datei mit dem Flag 'FILE_FLAG_WRITE_THROUGH' öffnen, um sicherzustellen, dass Daten sofort geschrieben werden (aber einige Geräte können dem Kernel anzulasten sein, wenn es um ihre eigenen Caches geht) ; Bei Pipes spielt dies jedoch nur für eine Pipe eine Rolle, auf die über das Netzwerk zugegriffen wird. – eryksun

Verwandte Themen