Angenommen, es gibt ein Skript, das so etwas tut:
# module writer.py
import sys
def write():
sys.stdout.write("foobar")
Angenommen, ich möchte die Ausgabe der write
Funktion erfassen und zur weiteren Verarbeitung in einer Variablen speichern. Die naive Lösung war:
# module mymodule.py
from writer import write
out = write()
print out.upper()
Das funktioniert aber nicht. Ich habe eine andere Lösung gefunden und sie funktioniert, aber bitte lassen Sie mich wissen, ob es einen besseren Weg gibt, das Problem zu lösen. Vielen Dank
import sys
from cStringIO import StringIO
# setup the environment
backup = sys.stdout
# ####
sys.stdout = StringIO() # capture output
write()
out = sys.stdout.getvalue() # release output
# ####
sys.stdout.close() # close the stream
sys.stdout = backup # restore original stdout
print out.upper() # post processing
value = subprocess.check_output(command, shell=True)
Hier ist eine Kontextmanager-Version Ihres Codes. Es ergibt eine Liste von zwei Werten; der erste ist stdout, der zweite ist stderr.
quelle
with capture() as out:
wird sich anders verhalten alswith capture() as out, err:
subprocess
funktioniert nicht, wenn Sie die Ausgabe verwenden und an sys.stdout / stderr umleiten. Dies liegt daran, dassStringIO
es sich nicht um ein echtes Dateiobjekt handelt und diefileno()
Funktion fehlt .Für zukünftige Besucher: Python 3.4 contextlib stellt dies direkt (siehe Python contextlib-Hilfe ) über den
redirect_stdout
Kontextmanager bereit :quelle
Dies ist das Dekorationsgegenstück meines ursprünglichen Codes.
writer.py
Bleibt das selbe:mymodule.py
wird leicht modifiziert:Und hier ist der Dekorateur:
quelle
Oder nutzen Sie Funktionen, die bereits vorhanden sind ...
quelle
Ab Python 3 können Sie auch
sys.stdout.buffer.write()
(bereits) codierte Byte-Strings in stdout schreiben (siehe stdout in Python 3 ). Wenn Sie dies tun,StringIO
funktioniert der einfache Ansatz nicht, da weder verfügbarsys.stdout.encoding
nochsys.stdout.buffer
verfügbar wäre.Ab Python 2.6 können Sie die
TextIOBase
API verwenden , die die fehlenden Attribute enthält:Diese Lösung funktioniert für Python 2> = 2.6 und Python 3. Bitte beachten Sie, dass unsere
sys.stdout.write()
nur Unicode-Zeichenfolgen und akzeptiertsys.stdout.buffer.write()
nur Byte-Zeichenfolgen akzeptiert. Dies ist möglicherweise nicht der Fall für alten Code, aber häufig für Code, der für die Ausführung auf Python 2 und 3 ohne Änderungen erstellt wurde.Wenn Sie Code unterstützen müssen, der Byte-Strings direkt an stdout sendet, ohne stdout.buffer zu verwenden, können Sie diese Variante verwenden:
Sie müssen die Codierung des Puffers nicht auf sys.stdout.encoding festlegen, dies ist jedoch hilfreich, wenn Sie diese Methode zum Testen / Vergleichen der Skriptausgabe verwenden.
quelle
Die Frage hier (das Beispiel, wie die Ausgabe umgeleitet wird, nicht das
tee
Teil) wird verwendetos.dup2
, um einen Stream auf Betriebssystemebene umzuleiten. Das ist schön, weil es auch für Befehle gilt, die Sie aus Ihrem Programm erzeugen.quelle
Ich denke, Sie sollten sich diese vier Objekte ansehen:
Beispiel:
UPD: Wie Eric in einem Kommentar sagte, sollte man sie nicht direkt verwenden, also habe ich sie kopiert und eingefügt.
quelle
Ich mag die Kontextmanager-Lösung, aber wenn Sie den Puffer benötigen, der mit der Unterstützung für geöffnete Dateien und Dateien gespeichert ist, können Sie so etwas tun.
verwenden
quelle