Wie kann ich die Ausgabe von Unterprozessen stdout und stderr ohne Verzerrung drucken und anzeigen?

8

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 ? Ich möchte jedoch nur den Wrapper in dieser Funktion verwenden.

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 .

    
perden 11.10.2011, 16:27
quelle

3 Antworten

10

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:

%Vor%

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:

  • Verwenden Sie die pywin32 -Bibliothek, um die native Win32-API
  • aufzurufen
  • Verwenden Sie SetNamedPipeHandleState mit PIPE_NOWAIT , um die stdout- und stderr-Pipes nicht blockierend zu machen
  • Verwenden Sie stattdessen WaitForMultipleObjects von select , um darauf zu warten, dass Daten verfügbar werden
  • Verwenden Sie ReadFile lies die Daten
Adam Rosenfield 11.10.2011, 17:45
quelle
0

Kombinieren Sie diese Antwort mit dies funktioniert der folgende Code für mich:

%Vor%     
Sundae 22.05.2014 08:11
quelle
0

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.

    
user1379351 21.06.2014 19:31
quelle

Tags und Links