Python Lesen von Teilprozess stdout und stderr getrennt, während die Erhaltung der Ordnung
Habe ich ein python-subprocess, dass ich versuche zu Lesen, - Ausgabe und Fehler-Ströme aus. Derzeit habe ich es zu arbeiten, aber ich bin nur in der Lage zu Lesen, aus stderr
nachdem ich fertig sind der Lektüre von stdout
. Hier ist, wie es aussieht:
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_iterator = iter(process.stdout.readline, b"")
stderr_iterator = iter(process.stderr.readline, b"")
for line in stdout_iterator:
# Do stuff with line
print line
for line in stderr_iterator:
# Do stuff with line
print line
Wie Sie sehen können, die stderr
for-Schleife kann nicht gestartet werden, bis die stdout
Schleife abgeschlossen. Wie kann ich ändern, diese Lesen zu können, sowohl in der richtigen Reihenfolge die Linien kommen?
Zu klären: ich noch brauchen, um in der Lage zu sagen, ob eine Zeile kam von stdout
oder stderr
weil Sie unterschiedlich behandelt werden in meinem code.
InformationsquelleAutor Luke Sapan | 2015-08-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den code in Ihre Frage von deadlock, wenn der untergeordnete Prozess genug produziert, die Ausgabe auf stderr (~100KB auf meine Linux-Maschine).
Es ist ein
communicate()
Methode, die ermöglicht das Lesen von sowohl stdout und stderr getrennt:Wenn Sie Lesen müssen, die streams während der Kind-Prozess noch läuft dann ist die tragbare Lösung ist die Verwendung von threads (nicht getestet):
Finden Sie unter:
stdout
undstderr
. Es ist sehr nah an, was ich brauche! Es ist nur wichtig für mich zu wissen, Wann einstderr
Zeile wird dann relativ zu einemstdout
Linie.Ich sehe keine Möglichkeit zum beibehalten der Reihenfolge und zu erfassen stdout/stderr getrennt. Sie können bekommen den einen oder anderen leicht. Unter Unix könnten Sie versuchen, eine select-Schleife ab, so dass der Effekt weniger offensichtlich. Es beginnt zu schauen, wie XY-problem: Bearbeiten Sie Ihre Frage und stellen einige Zusammenhänge auf, was Sie zu tun versuchen.
hier ist die Antwort mit einer select-Schleife. Wie ich schon sagte, wird Es nicht erhalten, um im Allgemeinen Fall, aber es könnte genug sein in einigen Fällen.
Als beide FDs sind unabhängig von einander, eine Nachricht kommen, die durch eine verzögert werden kann, so gibt es kein Konzept, "vor" und "nach" in diesem Fall...
warum bewahren die Reihenfolge? Fügen Sie einfach die timestamps Sortieren und am Ende.
InformationsquelleAutor jfs
Die Reihenfolge, in der ein Prozess schreibt Daten auf verschiedenen Leitungen verloren, nachdem Sie schreiben.
Es gibt keine Weise können Sie sagen, wenn stdout geschrieben wurden, bevor stderr.
Können Sie versuchen, Daten zu Lesen, gleichzeitig von mehreren Datei-Deskriptoren in einer nicht blockierenden Weise
sobald die Daten zur Verfügung, aber das würde nur minimieren Sie die Wahrscheinlichkeit, dass die Reihenfolge falsch ist.
Dieses Programm soll dies aufzeigen:
- und Ausgänge so etwas wie dieses:
if not s:
stattif len(s) == 0:
hier. Verwendenwhile fds:
stattwhile True: ... if fds == []: break
. Verwendenresults = collections.defaultdict(int); ...; results[data]+=1
stattresults = {}; ...; results[data] = results[data] + 1 if data in results else 1
Oder verwenden Sie
results = collections.Counter(); ...; results[data]+=1; ...; for data, count in results.most_common():
könnten Sie
data = b''.join([s for _, s in readfds(...)])
Sie sollte in der Nähe der Rohre zu vermeiden, sich auf den Müll colleciton freien Datei-Deskriptoren in der Mutter-und call -
p.wait()
zu ernten, wird der Kind-Prozess explizit.Hinweis: wenn es mehrere parallele Prozesse dann "langsam" kann nicht langsam genug sein, um die gewünschte Ausgabe erhalten
InformationsquelleAutor Jörg Schulz
Ich schrieb etwas dazu ein vor langer Zeit. Ich habe noch nicht portiert, es auf Python 3, aber es sollte nicht allzu schwierig sein (patches akzeptiert!)
Wenn man es standalone, Sie werden sehen, eine Menge von verschiedenen Optionen. In jedem Fall ermöglicht es Ihnen, zu unterscheiden von stderr stdout.
InformationsquelleAutor Patrick Maupin
Ich weiß, diese Frage ist sehr alt, aber diese Antwort kann anderen helfen, die stolpern auf dieser Seite in der Suche nach einer Lösung für eine ähnliche situation, so bin ich Entsendung es auf jeden Fall.
Habe ich baute ein einfaches python-snippet, Zusammenführen einer beliebigen Anzahl von Leitungen in einem einzigen. Natürlich, wie oben angegeben, kann die Bestellung nicht garantiert werden, aber dies ist so nah wie ich denke, dass kann man in Python.
Er erstellt einen thread für jedes der Rohre, liest Sie Zeile für Zeile und legt Sie in eine Queue (die FIFO). Der main-thread in einer Schleife durch die Warteschlange, wobei jede Zeile.
InformationsquelleAutor Marten Jacobs
Diese funktioniert bei mir (auf windows):
https://github.com/waszil/subpiper
InformationsquelleAutor waszil
Laut python-doc
Folgenden Beispiel tun können, was Sie wollen
test.py
printer.py
Ausgabe:
Sie haben Recht, ich missverstanden PO ' s Antwort.
InformationsquelleAutor simomo