Cosa sta facendo esattamente il file.flush () di Python?


137

Ho trovato questo nella documentazione di Python per File Objects :

flush () non scrive necessariamente i dati del file sul disco. Utilizzare flush () seguito da os.fsync () per garantire questo comportamento.

Quindi la mia domanda è: cosa sta flushfacendo esattamente Python ? Ho pensato che costringesse a scrivere dati sul disco, ma ora vedo che non lo fa. Perché?

Risposte:


220

Di solito sono coinvolti due livelli di buffering:

  1. Buffer interni
  2. Buffer del sistema operativo

I buffer interni sono buffer creati dal runtime / libreria / linguaggio su cui si sta programmando ed è pensato per accelerare le cose evitando chiamate di sistema per ogni scrittura. Invece, quando si scrive su un oggetto file, si scrive nel relativo buffer e ogni volta che il buffer si riempie, i dati vengono scritti nel file effettivo utilizzando le chiamate di sistema.

Tuttavia, a causa dei buffer del sistema operativo, ciò potrebbe non significare che i dati vengono scritti sul disco . Può semplicemente significare che i dati vengono copiati dai buffer gestiti dal runtime nei buffer gestiti dal sistema operativo.

Se si scrive qualcosa e finisce nel buffer (solo) e l'alimentazione viene interrotta sul computer, i dati non si trovano sul disco quando il computer si spegne.

Quindi, per aiutarvi con ciò avete i metodi flushe fsync, sui loro rispettivi oggetti.

Il primo flushscriverà semplicemente tutti i dati che si trovano in un buffer di programma nel file effettivo. In genere ciò significa che i dati verranno copiati dal buffer del programma al buffer del sistema operativo.

In particolare, ciò significa che se un altro processo ha lo stesso file aperto per la lettura, sarà in grado di accedere ai dati appena scaricati nel file. Tuttavia, ciò non significa necessariamente che sia stato "permanentemente" archiviato su disco.

Per fare ciò, è necessario chiamare il os.fsyncmetodo che garantisce che tutti i buffer del sistema operativo siano sincronizzati con i dispositivi di archiviazione per cui sono, in altre parole, quel metodo copierà i dati dai buffer del sistema operativo sul disco.

In genere non è necessario preoccuparsi di entrambi i metodi, ma se ci si trova in uno scenario in cui la paranoia su ciò che effettivamente finisce sul disco è una buona cosa, è necessario effettuare entrambe le chiamate secondo le istruzioni.


Addendum nel 2018.

Si noti che i dischi con meccanismi cache sono ora molto più comuni rispetto al 2013, quindi ora ci sono ancora più livelli di cache e buffer coinvolti. Mi assumo questi buffer saranno trattati dai richiami di sincronizzazione / a filo pure, ma io non lo so davvero.


10
Quando uso il with file('blah') as fd: #dostuffcostrutto, so che garantisce la chiusura del descrittore di file. Svuota o sincronizza anche?
Marcin,

3
@Marcin: arrossisce, ma NON si sincronizza.
Alex I,

8
fsyncè necessario per l'atomicità. non puoi aspettarti di chiudere un file, riaprirlo e trovare i tuoi contenuti senza una fsyncnel mezzo. Funziona spesso, ma non su Linux con ext4 e opzioni di mount predefinite per esempio. Inoltre, fsyncnon è garantito il vero capovolgere il ferro sui piatti, perché 1: fsync può essere disabilitato (in modalità laptop) e 2: il buffering interno del disco rigido potrebbe non essere istruito per lo svuotamento.
v.oddou,

1
c'è un modo per svuotare il buffer di un sistema operativo per tutti i file, se il file è scritto da un altro processo?
Nacht,

1
fsync è relativamente costoso. In generale, non stai scrivendo software mission-critical che necessita della conformità ACID al 100% e della durata per l'accesso al disco, e se lo fai probabilmente ne sei dolorosamente consapevole e dovresti essere consapevole dei passi che puoi prendere per ottenere queste garanzie . La chiamata a fsync attenderà che si verifichi l'accesso al disco fisico per scrivere i dati sul disco, mentre lo svuotamento e la chiusura attenderanno solo il trasferimento dei dati nella memoria cache. La differenza di velocità è probabilmente di diversi ordini di grandezza.
Lasse V. Karlsen,

10

Perché il sistema operativo potrebbe non farlo. L'operazione di scaricamento forza i dati del file nella cache dei file nella RAM, e da lì è compito del sistema operativo inviarlo effettivamente al disco.


6
Hai ragione, ma actuallyè relativo qui: se il dispositivo di destinazione ha abilitato la cache in scrittura, i dati potrebbero non aver raggiunto i piatti / chip effettivi al momento della os.fsync()restituzione.
Frédéric Hamidi,

7

Svuota il buffer interno, il che suppone che il sistema operativo scriva il buffer nel file. [1] Python utilizza il buffering predefinito del sistema operativo, a meno che non lo si configuri diversamente.

Ma a volte il sistema operativo sceglie ancora di non collaborare. Soprattutto con cose meravigliose come i ritardi di scrittura in Windows / NTFS. Fondamentalmente il buffer interno è svuotato, ma il buffer del sistema operativo è ancora trattenuto. Quindi devi dire al sistema operativo di scriverlo su disco con os.fsync()questi casi.

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


0

Fondamentalmente, flush () pulisce il tuo buffer RAM, il suo vero potere è che ti consente di continuare a scrivergli in seguito, ma non dovrebbe essere considerato come la migliore / sicura funzionalità di scrittura su file. Sta svuotando la RAM per ulteriori dati a venire, questo è tutto. Se vuoi assicurarti che i dati vengano scritti su file in modo sicuro, usa invece close ().

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.