Wie oft wird Python in eine Datei gespült?

228
  1. Wie oft wird Python in eine Datei gespült?
  2. Wie oft wird Python auf stdout gespült?

Ich bin mir nicht sicher über (1).

Was (2) betrifft, glaube ich, dass Python nach jeder neuen Zeile auf stdout gespült wird. Aber wenn Sie stdout überladen, um in eine Datei zu gelangen, wird es dann so oft geleert?

Tim McJilton
quelle

Antworten:

332

Für Dateivorgänge verwendet Python die Standardpufferung des Betriebssystems, sofern Sie dies nicht anders konfigurieren. Sie können eine Puffergröße, ungepuffert oder zeilengepuffert angeben.

Die Funktion open verwendet beispielsweise ein Argument für die Puffergröße.

http://docs.python.org/library/functions.html#open

"Das optionale Pufferargument gibt die gewünschte Puffergröße der Datei an:"

  • 0 bedeutet ungepuffert,
  • 1 bedeutet leitungsgepuffert,
  • Jeder andere positive Wert bedeutet, dass ein Puffer von (ungefähr) dieser Größe verwendet wird.
  • Eine negative Pufferung bedeutet, den Systemstandard zu verwenden, der normalerweise für tty-Geräte zeilengepuffert und für andere Dateien vollständig gepuffert ist.
  • Wenn nicht angegeben, wird die Systemvorgabe verwendet.

Code:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)
Corey Goldberg
quelle
23
+1 für den Teil "zeilengepuffert". Genau das habe ich gesucht und es funktioniert wie ein Zauber.
Rein
2
Wenn ich Python 3.4.3 verwende, open('file.txt', 'w', 1)bekomme ich die richtige Zeilenpufferung. Aber wenn ich etwas Größeres mache (ich wollte open('file.txt', 'w', 512)), puffert es io.DEFAULT_BUFFER_SIZE8192. Ist das ein Python-Fehler, ein Linux-Fehler oder ein ID10t-Fehler?
Bruno Bronosky
Ist es möglich, die Pufferung für die bereits geöffneten Streams zu ändern ? Angenommen, ich möchte stdoutzeilengepuffert werden, unabhängig davon, ob es sich um eine Konsole handelt oder ob sie in eine Datei umgeleitet wird.
Mikhail T.
1
@CharlieParker Wenn Sie write()ein Dateihandle aufrufen , wird die Ausgabe im Speicher gepuffert und akkumuliert, bis der Puffer voll ist. Zu diesem Zeitpunkt wird der Puffer "geleert" (Inhalt wird aus dem Puffer in die Datei geschrieben). Sie können den Puffer explizit leeren, indem Sie die flush()Methode für ein Dateihandle aufrufen .
Corey Goldberg
3
Beachten Sie, dass ungepuffert (0) nur im Binärmodus und zeilengepuffert (1) nur im Textmodus verfügbar ist.
ZaydH
172

Sie können den Puffer auch programmgesteuert mit der flush()Methode in eine Datei leeren .

with open('out.log', 'w+') as f:
    f.write('output is ')
    # some work
    s = 'OK.'
    f.write(s)
    f.write('\n')
    f.flush()
    # some other work
    f.write('done\n')
    f.flush()

Ich habe dies nützlich gefunden, wenn ich eine Ausgabedatei mit abschließe tail -f.

kortina
quelle
54
Aus den Dokumenten:Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
Bobismijnnaam
1
@ Bobismijnnaam nächstes Mal Link zu den genannten Dokumenten. Die einzige Referenz, die ich finden kann, stammt von github.com/jprzywoski/python-reference/blob/master/source/docs/… und ich weiß nicht, wer das ist.
Bruno Bronosky
5
@ Bruno Bronosky Guter Punkt. Docs: Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
Bobismijnnaam
Was mich verwirrt, ist, was der Begriff flushingüberhaupt bedeutet. Warum brauchen wir es? Wofür ist das? warum sollte es mich interessieren?
Charlie Parker
@CharlieParker Wenn Sie schreiben, schreiben Sie in eine Kopie (eines Teils) der Datei im RAM, die möglicherweise eine Weile nicht auf der Festplatte gespeichert wird. Dies verbessert die Leistung, kann jedoch zu Datenverlust führen, wenn diese Kopie nie geschrieben wird (Festplatte entfernt, Betriebssystemabstürze usw.). flush () weist Python an, diesen Puffer sofort auf die Festplatte zurückzuschreiben. (Dann weist os.fsync () das Betriebssystem an, dies ebenfalls zu tun. Es gibt viele Schichten von Puffern ...)
Rena
13

Ich weiß nicht, ob dies auch für Python gilt, aber ich denke, es hängt vom Betriebssystem ab, das Sie ausführen.

Unter Linux beispielsweise wird bei der Ausgabe an das Terminal der Puffer in einer neuen Zeile geleert, während bei der Ausgabe an Dateien nur geleert wird, wenn der Puffer voll ist (standardmäßig). Dies liegt daran, dass es effizienter ist, den Puffer weniger oft zu leeren, und der Benutzer es weniger wahrscheinlich bemerkt, wenn die Ausgabe nicht in einer neuen Zeile in einer Datei geleert wird.

Möglicherweise können Sie die Ausgabe automatisch spülen, wenn Sie dies benötigen.

EDIT: Ich denke, Sie würden in Python auf diese Weise automatisch spülen (basierend von hier )

#0 means there is no buffer, so all output
#will be auto-flushed
fsock = open('out.log', 'w', 0)
sys.stdout = fsock
#do whatever
fsock.close()
KLee1
quelle
12

Sie können die Standardpuffergröße auch überprüfen, indem Sie das schreibgeschützte Attribut DEFAULT_BUFFER_SIZE aus dem io-Modul aufrufen.

import io
print (io.DEFAULT_BUFFER_SIZE)
N Randhawa
quelle
1
Vielen Dank! Es ist gut zu wissen, dass Python es so festlegt, wie es das Betriebssystem definiert ... aber dies hilft herauszufinden, was das Betriebssystem vordefiniert.
Cometsong
2

Hier ist ein anderer Ansatz, bis das OP entscheidet, welchen er bevorzugt.

Wenn Sie den folgenden Code __init__vor jedem anderen Code in die PY-Datei aufnehmen, werden mit printund gedruckte Nachrichten und Fehler nicht mehr in Abletons Log.txt protokolliert, sondern in separaten Dateien auf Ihrer Festplatte:

import sys

path = "/Users/#username#"

errorLog = open(path + "/stderr.txt", "w", 1)
errorLog.write("---Starting Error Log---\n")
sys.stderr = errorLog
stdoutLog = open(path + "/stdout.txt", "w", 1)
stdoutLog.write("---Starting Standard Out Log---\n")
sys.stdout = stdoutLog

(Ändern Sie für Mac #username#den Namen Ihres Benutzerordners. Unter Windows hat der Pfad zu Ihrem Benutzerordner ein anderes Format.)

Wenn Sie die Dateien in einem Texteditor öffnen, der den Inhalt aktualisiert, wenn die Datei auf der Festplatte geändert wird (Beispiel für Mac: TextEdit nicht, TextWrangler jedoch), werden die Protokolle in Echtzeit aktualisiert.

Credits: Dieser Code wurde größtenteils aus den LiveAPI-Kontrolloberflächenskripten von Nathan Ramella kopiert

Mattijs
quelle