Ich versuche, von stdout
und stderr
von einem Popen
zu lesen und sie auszudrucken. Der Befehl, den ich mit Popen leite ist die folgendePopen gibt keine Ausgabe sofort wenn verfügbar
#!/bin/bash
i=10
while ((i > 0)); do
sleep 1s
echo heyo-$i
i="$((i-1))"
done
echo 'to error' >&2
Als ich dies in der Shell ausgeführt, ich eine Zeile der Ausgabe zu erhalten und dann eine zweite Pause und dann eine Zeile wieder, usw. Aber ich bin nicht in der Lage zu Erstelle das mit Python neu. Ich starte zwei Threads, jeweils einen von stdout
und stderr
zu lesen, lege die gelesenen Zeilen in einen Queue
und einen anderen Thread, der Elemente aus dieser Warteschlange aufnimmt und ausdruckt. Aber damit sehe ich, dass alle Ausgaben auf einmal ausgedruckt werden, nachdem der Subprozess beendet ist. Ich möchte, dass die Zeilen gedruckt werden, wenn sie echo
'ed sind.
Hier ist meine Python-Code:
# The `randoms` is in the $PATH
proc = sp.Popen(['randoms'], stdout=sp.PIPE, stderr=sp.PIPE, bufsize=0)
q = Queue()
def stream_watcher(stream, name=None):
"""Take lines from the stream and put them in the q"""
for line in stream:
q.put((name, line))
if not stream.closed:
stream.close()
Thread(target=stream_watcher, args=(proc.stdout, 'out')).start()
Thread(target=stream_watcher, args=(proc.stderr, 'err')).start()
def displayer():
"""Take lines from the q and add them to the display"""
while True:
try:
name, line = q.get(True, 1)
except Empty:
if proc.poll() is not None:
break
else:
# Print line with the trailing newline character
print(name.upper(), '->', line[:-1])
q.task_done()
print('-*- FINISHED -*-')
Thread(target=displayer).start()
Irgendwelche Ideen? Was fehlt mir hier?
Was Sie vermissen ist, dass die Pipeline gepuffert ist. Ich weiß nicht, wie Sie den Bash-Prozess dazu bringen können, den Puffer zu leeren. –
Ich glaube auch nicht, dass Stream Watcher funktioniert. 'for line in stream' wird alle Zeilen auslassen, die anfänglich verfügbar sind, dann schließe den stdout/stderr - ich glaube nicht, dass du sie zuerst schließen willst, und du wartest nicht und checkst noch mehr Zeilen nach erscheinen. – agf
@SvenMarnach, Pipeline wird von Python gepuffert? Wenn ja, wie kann ich sagen, dass ich das nicht tun soll und stattdessen die Daten angeben soll? @agf, die for-Schleife wird nicht enden, bis eine 'StopIteration' ausgelöst wird, was meiner Meinung nach geschieht, wenn der Subprozess seine Seite der Pipe schließt. Deshalb schließe ich den Stream sofort. Außerdem überprüfe ich, ob der Prozess im Displayer-Thread läuft. –