Was genau macht Pythons file.flush ()?

137

Ich habe dies in der Python- Dokumentation für Dateiobjekte gefunden :

flush () schreibt die Daten der Datei nicht unbedingt auf die Festplatte. Verwenden Sie flush () gefolgt von os.fsync (), um dieses Verhalten sicherzustellen.

Meine Frage ist also: Was genau macht Python flush? Ich dachte, dass es gezwungen ist, Daten auf die Festplatte zu schreiben, aber jetzt sehe ich, dass dies nicht der Fall ist. Warum?

Geek
quelle

Antworten:

219

Es gibt normalerweise zwei Pufferebenen:

  1. Interne Puffer
  2. Betriebssystempuffer

Die internen Puffer sind Puffer, die von der Laufzeit / Bibliothek / Sprache erstellt werden, für die Sie programmieren, und sollen die Dinge beschleunigen, indem Systemaufrufe bei jedem Schreibvorgang vermieden werden. Wenn Sie in ein Dateiobjekt schreiben, schreiben Sie stattdessen in dessen Puffer. Wenn der Puffer voll ist, werden die Daten mithilfe von Systemaufrufen in die eigentliche Datei geschrieben.

Aufgrund der Betriebssystempuffer bedeutet dies jedoch möglicherweise nicht, dass die Daten auf die Festplatte geschrieben werden . Dies kann nur bedeuten, dass die Daten aus den von Ihrer Laufzeit verwalteten Puffern in die vom Betriebssystem verwalteten Puffer kopiert werden.

Wenn Sie etwas schreiben und es (nur) im Puffer landet und die Stromversorgung Ihres Computers unterbrochen wird, befinden sich diese Daten beim Ausschalten des Computers nicht auf der Festplatte.

Also, um zu helfen mit , dass Sie die flushund fsyncMethoden, auf ihre jeweiligen Objekte.

Die erste flushMethode schreibt einfach alle Daten, die in einem Programmpuffer verbleiben, in die eigentliche Datei. In der Regel bedeutet dies, dass die Daten aus dem Programmpuffer in den Betriebssystempuffer kopiert werden.

Dies bedeutet insbesondere, dass ein anderer Prozess, der dieselbe Datei zum Lesen geöffnet hat, auf die Daten zugreifen kann, die Sie gerade in die Datei geschrieben haben. Dies bedeutet jedoch nicht unbedingt, dass es "dauerhaft" auf der Festplatte gespeichert wurde.

Dazu müssen Sie die os.fsyncMethode aufrufen , mit der sichergestellt wird, dass alle Betriebssystempuffer mit den Speichergeräten synchronisiert sind, für die sie bestimmt sind. Mit anderen Worten, diese Methode kopiert Daten aus den Betriebssystempuffern auf die Festplatte.

Normalerweise müssen Sie sich nicht mit beiden Methoden beschäftigen, aber wenn Sie sich in einem Szenario befinden, in dem Paranoia darüber, was tatsächlich auf der Festplatte landet, eine gute Sache ist, sollten Sie beide Anrufe wie angewiesen tätigen.


Nachtrag im Jahr 2018.

Beachten Sie, dass Festplatten mit Cache-Mechanismen heute weitaus häufiger sind als 2013, sodass jetzt noch mehr Ebenen für Caching und Puffer beteiligt sind. Ich gehe davon aus, dass diese Puffer auch von den Sync / Flush-Aufrufen verarbeitet werden, aber ich weiß es nicht wirklich.

Lasse V. Karlsen
quelle
10
Wenn ich das with file('blah') as fd: #dostuffKonstrukt verwende, weiß ich, dass es das Schließen des Dateideskriptors garantiert. Spült oder synchronisiert es auch?
Marcin
3
@Marcin: Es wird gespült, aber NICHT synchronisiert.
Alex I
8
fsyncist für die Atomizität notwendig. Sie können nicht erwarten, eine Datei zu schließen, sie erneut zu öffnen und Ihren Inhalt ohne eine fsyncin der Mitte zu finden. Es funktioniert oft, aber nicht unter Linux mit ext4 und Standard-Mount-Optionen. Es fsyncist auch nicht garantiert, dass das Bügeleisen auf den Platten wirklich magnetisch umgedreht wird, da 1: fsync deaktiviert werden kann (im Laptop-Modus) und 2: die interne Pufferung der Festplatte möglicherweise nicht zum Spülen angewiesen wird.
v.oddou
1
Gibt es eine Möglichkeit, den Puffer eines Betriebssystems für alle Dateien zu leeren, wenn die Datei von einem anderen Prozess geschrieben wurde?
Nacht
1
fsync ist relativ teuer. Im Allgemeinen schreiben Sie keine geschäftskritische Software, die 100% ACID-Konformität und Haltbarkeit für den Festplattenzugriff benötigt. Wenn Sie dies tun, sind Sie sich dessen wahrscheinlich schmerzlich bewusst und sollten sich der Schritte bewusst sein, die Sie unternehmen können, um diese Garantien zu erhalten . Wenn Sie fsync aufrufen, wird auf den physischen Festplattenzugriff gewartet, um die Daten auf die Festplatte zu schreiben, während beim Löschen und Schließen nur darauf gewartet wird, dass Daten in den Cache-Speicher verschoben werden. Der Geschwindigkeitsunterschied beträgt wahrscheinlich mehrere Größenordnungen.
Lasse V. Karlsen
10

Weil das Betriebssystem dies möglicherweise nicht tut. Durch den Flush-Vorgang werden die Dateidaten in den Dateicache im RAM verschoben, und von dort aus muss das Betriebssystem sie tatsächlich an die Festplatte senden.

Ignacio Vazquez-Abrams
quelle
6
Sie haben Recht, sind aber actuallyhier relativ: Wenn auf dem Zielgerät das Schreib-Caching aktiviert ist, haben die Daten bei der os.fsync()Rückgabe möglicherweise nicht die tatsächlichen Platten / Chips erreicht .
Frédéric Hamidi
7

Es löscht den internen Puffer, der das Betriebssystem veranlassen soll, den Puffer in die Datei zu schreiben. [1] Python verwendet die Standardpufferung des Betriebssystems, sofern Sie dies nicht anders konfigurieren.

Aber manchmal entscheidet sich das Betriebssystem immer noch dafür, nicht zusammenzuarbeiten. Besonders bei wunderbaren Dingen wie Schreibverzögerungen in Windows / NTFS. Grundsätzlich wird der interne Puffer geleert, aber der Betriebssystempuffer hält ihn immer noch fest. os.fsync()In diesen Fällen müssen Sie das Betriebssystem anweisen, es auf die Festplatte zu schreiben .

[1] http://docs.python.org/library/stdtypes.html

Dan
quelle
0

Grundsätzlich bereinigt Flush () Ihren RAM-Puffer. Seine eigentliche Stärke besteht darin, dass Sie danach weiter darauf schreiben können - aber es sollte nicht als die beste / sicherste Funktion zum Schreiben in eine Datei angesehen werden. Es spült Ihren RAM, damit mehr Daten kommen, das ist alles. Wenn Sie sicherstellen möchten, dass Daten sicher in die Datei geschrieben werden, verwenden Sie stattdessen close ().

zA.
quelle