Ist die Ausgabepufferung im Python-Interpreter für standardmäßig aktiviert sys.stdout
?
Wenn die Antwort positiv ist, wie können Sie sie deaktivieren?
Bisherige Vorschläge:
- Verwenden Sie den
-u
Befehlszeilenschalter - Wickeln Sie
sys.stdout
ein Objekt ein, das nach jedem Schreibvorgang gelöscht wird - Setze
PYTHONUNBUFFERED
env var sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Gibt es eine andere Möglichkeit, während der Ausführung ein globales Flag in sys
/ sys.stdout
programmgesteuert zu setzen?
-u
ist, dass es nicht für kompilierten Bytecode oder für Apps mit einer__main__.py
Datei als Einstiegspunkt funktioniert .Antworten:
Von Magnus Lycka Antwort auf eine Mailingliste :
quelle
#!/usr/bin/env python -u
funktioniert nicht !! siehe hier__getattr__
nur um Vererbung zu vermeiden?!iter()
anstelle derwhile
Schleife verwenden :for line in iter(pipe.readline, ''):
. Sie brauchen es nicht auf Python 3, wo esfor line in pipe:
so schnell wie möglich liefert.Ich möchte meine Antwort lieber in Wie lösche ich die Ausgabe der Druckfunktion? oder in Pythons Druckfunktion, die den Puffer beim Aufruf leert? , aber da sie als Duplikate von diesem markiert wurden (was ich nicht zustimme), werde ich es hier beantworten.
Seit Python 3.3 unterstützt print () das Schlüsselwortargument "flush" ( siehe Dokumentation ):
quelle
Credits: "Sebastian", irgendwo auf der Python-Mailingliste.
quelle
flush=True
Parameter anprint()
Python seit Python 3.3 übergeben.os.fdopen(sys.stdout.fileno(), 'wb', 0)
(beachten Sie dieb
für binäre) undflush=True
arbeiten für mich in 3.6.4. Wenn Sie jedoch verwenden subprocess ein anderes Skript zu starten, stellen Sie sicher , haben Sie angegebenpython3
, wenn Sie mehrere Instanzen von Python installiert haben.os.fdopen(sys.stdout.fileno(), 'wb', 0)
Sie ein Binärdateiobjekt, keinenTextIO
Stream. Sie müsstenTextIOWrapper
der Mischung ein hinzufügen (stellen Sie sicher, dasswrite_through
alle Puffer entfernt werden, oder verwenden Sieline_buffering=True
diese Option , um nur Zeilenumbrüche zu löschen).Ja, so ist es.
Sie können es in der Befehlszeile mit dem Schalter "-u" deaktivieren.
Alternativ können Sie bei jedem Schreibvorgang .flush () für sys.stdout aufrufen (oder es mit einem Objekt umschließen, das dies automatisch ausführt).
quelle
Dies bezieht sich auf die Antwort von Cristóvão D. Sousa, aber ich konnte noch keinen Kommentar abgeben.
Eine einfache Möglichkeit, das
flush
Schlüsselwortargument von Python 3 zu verwenden, um immer eine ungepufferte Ausgabe zu erhalten, ist:Danach spült der Druck die Ausgabe immer direkt (außer wenn
flush=False
angegeben).Beachten Sie, (a) dass dies die Frage nur teilweise beantwortet, da nicht die gesamte Ausgabe umgeleitet wird. Aber ich denke, dies
print
ist die häufigste Methode zum Erstellen von Ausgaben fürstdout
/stderr
in Python. Daher decken diese beiden Zeilen wahrscheinlich die meisten Anwendungsfälle ab.Beachten Sie (b), dass es nur in dem Modul / Skript funktioniert, in dem Sie es definiert haben. Dies kann beim Schreiben eines Moduls hilfreich sein, da es nicht mit dem Modul in Konflikt gerät
sys.stdout
.Python 2 liefert das
flush
Argument nicht, aber Sie können eine Python 3-print
Funktion emulieren, wie hier beschrieben: https://stackoverflow.com/a/27991478/3734258 .quelle
flush
Nur dass es in python2 kein kwarg gibt.Ohne das Speichern der alten sys.stdout ist disable_stdout_buffering () nicht idempotent, und mehrere Aufrufe führen zu einem Fehler wie dem folgenden:
Eine andere Möglichkeit ist:
(Das Anhängen an gc.garbage ist keine so gute Idee, da hier unfrequente Zyklen abgelegt werden und Sie möglicherweise nach diesen suchen möchten.)
quelle
stdout
noch weiterlebt,sys.__stdout__
wie einige vorgeschlagen haben, wird das Müllding nicht notwendig sein, oder? Es ist allerdings ein cooler Trick.ValueError: can't have unbuffered text I/O
beim Aufrufen die Ausnahme ausgelöst wirdprint()
.Folgendes funktioniert in Python 2.6, 2.7 und 3.2:
quelle
OSError: [Errno 29] Illegal seek
für die Zeilesys.stdout = os.fdopen(sys.stdout.fileno(), 'a+', buf_arg)
Ja, es ist standardmäßig aktiviert. Sie können es deaktivieren, indem Sie beim Aufrufen von Python die Option -u in der Befehlszeile verwenden.
quelle
Sie können Python auch mit dem Dienstprogramm stdbuf ausführen :
stdbuf -oL python <script>
quelle
-oL
) wird immer noch gepuffert - siehe f / e stackoverflow.com/questions/58416853/… und fragt, warumend=''
die Ausgabe nicht mehr sofort angezeigt wird.print(..., end='', flush=True)
wo dies nicht wichtig ist? OTOH: Wenn mehrere Programme gleichzeitig auf dieselbe Ausgabe schreiben, verschiebt sich der Kompromiss tendenziell vom sofortigen Fortschritt zur Reduzierung von Ausgabeverwechslungen, und die Zeilenpufferung wird attraktiv. Vielleicht ist es also besser, nicht explizit zu schreibenflush
und die Pufferung extern zu steuern?flush
. Die externeIn Python 3 können Sie die Druckfunktion mit einem Affen-Patch versehen, um immer Flush = True zu senden:
Wie in einem Kommentar erwähnt, können Sie dies vereinfachen, indem Sie den Parameter flush an einen Wert binden, und zwar über
functools.partial
:quelle
functools.partial
?print = functools.partial(print, flush=True)
funktioniert gut für mich.import builtins; builtins.print = partial(print, flush=True)
Sie können auch fcntl verwenden, um die Dateiflaggen im laufenden Betrieb zu ändern.
quelle
Es ist möglich, nur die
write
Methode vonsys.stdout
mit einer aufzurufen, die aufruftflush
. Die vorgeschlagene Methodenimplementierung ist unten aufgeführt.Der Standardwert des
w
Arguments behält die ursprünglichewrite
Methodenreferenz bei. Nachdemwrite_flush
definiert wurde, wird das Originalwrite
möglicherweise überschrieben.Der Code geht davon aus, dass er auf
stdout
diese Weise importiert wirdfrom sys import stdout
.quelle
Sie können eine ungepufferte Datei erstellen und diese Datei sys.stdout zuweisen.
Sie können das vom System bereitgestellte Standard nicht auf magische Weise ändern. da es vom Betriebssystem an Ihr Python-Programm geliefert wird.
quelle
Variante, die ohne Absturz funktioniert (zumindest unter win32; Python 2.7, Ipython 0.12) und anschließend (mehrmals) aufgerufen wird:
quelle
sys.stdout is sys.__stdout__
anstatt sich darauf zu verlassen, dass das Ersatzobjekt ein Namensattribut hat?(Ich habe einen Kommentar gepostet, aber er ist irgendwie verloren gegangen. Also nochmal :)
Wie ich bemerkt habe, verhält sich CPython (zumindest unter Linux) unterschiedlich, je nachdem, wohin die Ausgabe geht. Wenn es zu einem tty geht, wird die Ausgabe nach jedem 'geleert.
\n'
Wenn es zu einer Pipe / einem Prozess geht, wird es gepuffert und Sie können die oben empfohlenen
flush()
Lösungen oder die oben empfohlene Option -u verwenden .In geringem Zusammenhang mit der Ausgabepufferung:
Wenn Sie mit über die Zeilen in der Eingabe iterieren
for line in sys.stdin:
...
Dann sammelt die for- Implementierung in CPython die Eingabe für eine Weile und führt dann den Schleifenkörper für eine Reihe von Eingabezeilen aus. Wenn Ihr Skript im Begriff ist, eine Ausgabe für jede Eingabezeile zu schreiben, sieht dies möglicherweise wie eine Ausgabepufferung aus, es wird jedoch tatsächlich gestapelt, und daher
flush()
hilft keine der Techniken usw. dabei. Interessanterweise haben Sie dieses Verhalten bei Pypy nicht . Um dies zu vermeiden, können Sie verwendenwhile True: line=sys.stdin.readline()
...
quelle
for line in sys.stdin
vs.for line in iter(sys.stdin.readline, "")
for line in sys.stdin
bietet eine verzögerte Antwort)Eine Möglichkeit, eine ungepufferte Ausgabe zu erhalten, besteht darin,
sys.stderr
anstelle vonsys.stdout
oder einfach aufzurufensys.stdout.flush()
, um das Schreiben explizit zu erzwingen.Sie können alles, was gedruckt wurde, leicht umleiten, indem Sie Folgendes tun:
Oder um nur für eine bestimmte
print
Anweisung umzuleiten :Um stdout zurückzusetzen, können Sie einfach Folgendes tun:
quelle