Vielleicht gibt es jemanden im Äther, der mir dabei helfen kann. (Ich habe eine Reihe von ähnlichen Fragen dazu auf SO gesehen, aber keine befassen sich sowohl mit Standard-und Standard-Fehler oder befassen sich mit einer Situation ganz wie meine, daher diese neue Frage.)
Ich habe eine Python-Funktion, die einen Unterprozess öffnet, darauf wartet, dass sie abgeschlossen wird, und dann den Rückkehrcode sowie den Inhalt der Standard- und Standardfehler-Pipes ausgibt. Während der Prozess ausgeführt wird, möchte ich auch die Ausgabe beider Pipes anzeigen, wenn sie gefüllt sind. Mein erster Versuch hat zu so etwas geführt:
%Vor% Es gibt jedoch ein paar Probleme damit. Da read()
bis zu EOF
gelesen wird, wird die erste Zeile der while
-Schleife erst zurückgegeben, wenn der Subprozess die Pipe geschlossen hat.
Ich könnte die read()
zugunsten von read(int)
ersetzen, aber die gedruckte Ausgabe ist verzerrt, abgeschnitten am Ende der gelesenen Zeichen. Ich könnte readline()
als Ersatz verwenden, aber die gedruckte Ausgabe ist mit abwechselnden Zeilen der Ausgabe und Fehlern verzerrt, wenn viele von beiden gleichzeitig auftreten.
Vielleicht gibt es eine read-until-end-of-buffer()
Variante, die mir nicht bekannt ist? Oder vielleicht kann es implementiert werden?
Vielleicht ist es am besten, einen sys.stdout
-Wrapper zu implementieren, wie in dieser Antwort auf einen anderen Beitrag
Irgendwelche anderen Ideen aus der Community?
Ich schätze die Hilfe! :)
BEARBEITEN : Die Lösung sollte wirklich plattformübergreifend sein, aber wenn Sie Ideen haben, die das nicht sind, teilen Sie sie bitte mit, damit das Brainstorming weitergeht.
Für einen weiteren Python-Subprozess-Head Scratcher werfen Sie einen Blick auf eine weitere meiner Fragen zu Bilanzierung des Overhead des Subprozesses im Timing .
Machen Sie die Pipes nicht blockierend, indem Sie fcntl.fcntl
verwenden und select.select
, um darauf zu warten, dass in beiden Pipes Daten verfügbar werden. Zum Beispiel:
Beachten Sie, dass fcntl
nur auf Unix-ähnlichen Plattformen, einschließlich Cygwin, verfügbar ist.
Wenn es unter Windows ohne Cygwin funktioniert, ist es machbar, aber es ist viel, viel härter. Du musst:
SetNamedPipeHandleState
mit PIPE_NOWAIT
, um die stdout- und stderr-Pipes nicht blockierend zu machen WaitForMultipleObjects
von select
, um darauf zu warten, dass Daten verfügbar werden ReadFile
lies die Daten Kombinieren Sie diese Antwort mit dies funktioniert der folgende Code für mich:
%Vor%Als ich es getestet habe, schien es, dass readline () blockiert. Allerdings konnte ich auf stdout und stderr separat zugreifen, indem ich Threads nutze. Codebeispiel wie folgt:
%Vor%Ich bin mir jedoch nicht sicher, dass das Thread-sicher ist.
Tags und Links python subprocess