Beim Versuch, die Standardausgabe von einem Python-Skript in eine Textdatei ( python script.py > log
) zu schreiben , wird die Textdatei beim Starten des Befehls erstellt, der eigentliche Inhalt wird jedoch erst nach Abschluss des Python-Skripts geschrieben. Zum Beispiel:
script.py:
import time
for i in range(10):
print('bla')
time.sleep(5)
druckt alle 5 Sekunden auf stdout, wenn mit aufgerufen wird python script.py
, aber wenn ich aufrufe python script.py > log
, bleibt die Größe der Protokolldatei Null, bis das Skript beendet ist. Ist es möglich, direkt in die Protokolldatei zu schreiben, sodass Sie den Fortschritt des Skripts verfolgen können (z. B. mithilfe von tail
)?
EDIT Es stellt sich heraus, dass python -u script.py
dies der Trick ist, ich wusste nichts über das Puffern von stdout.
Antworten:
Dies geschieht normalerweise, weil, wenn der Prozess STDOUT zu etwas anderem als einem Terminal umgeleitet wird, die Ausgabe in einem betriebssystemspezifischen Puffer gepuffert wird (in vielen Fällen vielleicht 4k oder 8k). Umgekehrt wird STDOUT bei der Ausgabe an ein Terminal zeilenweise oder gar nicht gepuffert, sodass die Ausgabe nach jedem
\n
oder für jedes Zeichen erfolgt.Sie können die STDOUT-Pufferung im Allgemeinen mit dem
stdbuf
Dienstprogramm ändern :Wenn Sie dies jetzt tun
tail -F log
, sollten Sie jede Zeilenausgabe sofort sehen, wenn sie generiert wird.Alternativ sollte das explizite Spülen des Ausgabestreams nach jedem Druck dasselbe erreichen. Es sieht so aus, als
sys.stdout.flush()
sollte dies in Python erreicht werden. Wenn Sie Python 3.3 oder höher verwenden, dieprint
hat die Funktion auch einflush
Schlüsselwort , das dies tut:print('hello', flush=True)
.quelle
python -u script.py
dies der Trick ist. BEARBEITEN So viele Antworten auf einmal, ich habe Ihre angenommen, da sie mich in Richtung Pufferung wies.--line-buffered
fürgrep
, andere jedoch nicht.stdbuf
ist das allgemeine Hilfsprogramm, um mit denen umzugehen, die es nicht tun.stdbuf -o0 python script.py > log
unter diesen bestimmten Umständen?-oL
ist ein Kompromiss. Im Allgemeinen bieten größere Puffer eine bessere Leistung bei der Umleitung (weniger Systemaufrufe und weniger E / A-Vorgänge). Wenn es jedoch unbedingt erforderlich ist, jedes Zeichen so zu sehen, wie es ausgegeben wird, ist yes-o0
erforderlich.Dies sollte den Job machen:
Da Python das
stdout
standardmäßig puffert, habe ich hier verwendetsys.stdout.flush()
, um den Puffer zu leeren.Eine andere Lösung wäre die Verwendung des
-u
(ungepufferten) Schalters vonpython
. So wird das folgende auch tun:quelle
Eine Variation des Themas der Verwendung von Pythons eigener Option für die ungepufferte Ausgabe wäre die Verwendung
#!/usr/bin/python -u
als erste Zeile.Wenn
#!/usr/bin/env python
dieses zusätzliche Argument nicht funktioniert, kann man es alternativ auchPYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt
in zwei Schritten ausführen :quelle
Sie sollten
flush=True
an dieprint
Funktion übergeben:Gemäß der Dokumentation wird standardmäßig
print
nichts zum Löschen erzwungen:Und die Dokumentation für
sys
's Strems sagt:Wenn Sie mit einer alten Version von Python nicht weiterkommen, müssen Sie die
flush
Methode dessys.stdout
Streams aufrufen :quelle
DigitalTrauma
10 Stunden zuvor gesagt wurde. Du solltest seinen Beitrag positiv bewerten, nicht das Gleiche noch einmal posten.print(flush=True)
diese Antwort nach meiner von einem Drittautor hinzugefügt . Ich finde es geschmacklos, Inhalte aus meiner Antwort herauszureißen, um sie ohne Anerkennung in eine andere zu stecken. Ich beschloss, meine Antwort nur deshalb hinzuzufügen, weil in keiner Antwort der einfachste Weg genannt wurde, das zu erreichen, was das OP in neueren Versionen von Python wollte, und ich fügte der Vollständigkeit halber den "alten Weg" hinzu. Bitte überprüfen Sie das nächste Mal den Revisionsverlauf, bevor Sie Kommentare abgeben oder Abstimmungen vornehmen.__future__
Import:from __future__ import print_function
. Aber ja, das dient nur der Kompatibilität mit Python 3