Ich suche nach einer Python-Lösung, mit der ich die Ausgabe eines Befehls in einer Datei speichern kann, ohne sie vor der Konsole zu verbergen.
Zu Ihrer Information : Ich frage nach tee (als Unix-Befehlszeilenprogramm) und nicht nach der gleichnamigen Funktion aus dem Python-Intertools-Modul.
Einzelheiten
- Python-Lösung (nicht aufrufend
tee
, unter Windows nicht verfügbar) - Ich muss keine Eingabe für stdin für den aufgerufenen Prozess bereitstellen
- Ich habe keine Kontrolle über das aufgerufene Programm. Ich weiß nur, dass es etwas an stdout und stderr ausgibt und mit einem Exit-Code zurückgibt.
- Zum Aufrufen externer Programme (Unterprozess)
- Für beide arbeiten
stderr
undstdout
- In der Lage zu sein, zwischen stdout und stderr zu unterscheiden, weil ich möglicherweise nur eines davon auf der Konsole anzeigen möchte oder versuchen könnte, stderr mit einer anderen Farbe auszugeben - dies bedeutet, dass dies
stderr = subprocess.STDOUT
nicht funktioniert. - Live-Ausgabe (progressiv) - Der Prozess kann lange dauern und ich kann es kaum erwarten, bis er abgeschlossen ist.
- Python 3-kompatibler Code (wichtig)
Verweise
Hier sind einige unvollständige Lösungen, die ich bisher gefunden habe:
- http://devlishgenius.blogspot.com/2008/10/logging-in-real-time-in-python.html (mkfifo funktioniert nur unter Unix)
- http://blog.kagesenshi.org/2008/02/teeing-python-subprocesspopen-output.html (funktioniert überhaupt nicht)
Diagramm http://blog.i18n.ro/wp-content/uploads/2010/06/Drawing_tee_py.png
Aktueller Code (zweiter Versuch)
#!/usr/bin/python
from __future__ import print_function
import sys, os, time, subprocess, io, threading
cmd = "python -E test_output.py"
from threading import Thread
class StreamThread ( Thread ):
def __init__(self, buffer):
Thread.__init__(self)
self.buffer = buffer
def run ( self ):
while 1:
line = self.buffer.readline()
print(line,end="")
sys.stdout.flush()
if line == '':
break
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdoutThread = StreamThread(io.TextIOWrapper(proc.stdout))
stderrThread = StreamThread(io.TextIOWrapper(proc.stderr))
stdoutThread.start()
stderrThread.start()
proc.communicate()
stdoutThread.join()
stderrThread.join()
print("--done--")
#### test_output.py ####
#!/usr/bin/python
from __future__ import print_function
import sys, os, time
for i in range(0, 10):
if i%2:
print("stderr %s" % i, file=sys.stderr)
else:
print("stdout %s" % i, file=sys.stdout)
time.sleep(0.1)
Echte Ausgabe
stderr 1
stdout 0
stderr 3
stdout 2
stderr 5
stdout 4
stderr 7
stdout 6
stderr 9
stdout 8
--done--
Bei der erwarteten Ausgabe sollten die Zeilen bestellt werden. Bemerkung, das Ändern des Popen, um nur ein PIPE zu verwenden, ist nicht erlaubt, da ich im wirklichen Leben verschiedene Dinge mit stderr und stdout machen möchte.
Auch im zweiten Fall war ich nicht in der Lage, Echtzeit-Outs zu erhalten. Tatsächlich gingen alle Ergebnisse ein, als der Prozess abgeschlossen war. Standardmäßig sollte Popen keine Puffer verwenden (bufsize = 0).