¿Qué está haciendo exactamente file.flush () de Python?

137

Encontré esto en la documentación de Python para File Objects :

flush () no necesariamente escribe los datos del archivo en el disco. Utilice flush () seguido de os.fsync () para garantizar este comportamiento.

Entonces mi pregunta es: ¿qué está flushhaciendo exactamente Python ? Pensé que obligaba a escribir datos en el disco, pero ahora veo que no. ¿Por qué?

friki
fuente

Respuestas:

220

Normalmente hay dos niveles de almacenamiento intermedio involucrados:

  1. Tampones internos
  2. Tampones del sistema operativo

Los búferes internos son búferes creados por el tiempo de ejecución / biblioteca / lenguaje contra el que está programando y están destinados a acelerar las cosas al evitar las llamadas al sistema para cada escritura. En cambio, cuando escribe en un objeto de archivo, escribe en su búfer, y cada vez que el búfer se llena, los datos se escriben en el archivo real mediante llamadas al sistema.

Sin embargo, debido a los búferes del sistema operativo, esto podría no significar que los datos se escriben en el disco . Puede significar que los datos se copian de las memorias intermedias mantenidas por su tiempo de ejecución en las memorias intermedias mantenidas por el sistema operativo.

Si escribe algo y termina en el búfer (solo), y se corta la alimentación de su máquina, esos datos no están en el disco cuando la máquina se apaga.

Entonces, para ayudar con eso, tiene los métodos flushy fsync, en sus respectivos objetos.

El primero, flushsimplemente escribirá cualquier dato que permanezca en un búfer de programa en el archivo real. Normalmente, esto significa que los datos se copiarán del búfer del programa al búfer del sistema operativo.

Específicamente, lo que esto significa es que si otro proceso tiene ese mismo archivo abierto para lectura, podrá acceder a los datos que acaba de vaciar al archivo. Sin embargo, no significa necesariamente que se haya almacenado "permanentemente" en el disco.

Para hacer eso, debe llamar al os.fsyncmétodo que garantiza que todos los búferes del sistema operativo estén sincronizados con los dispositivos de almacenamiento para los que están destinados, en otras palabras, ese método copiará los datos de los búferes del sistema operativo al disco.

Por lo general, no necesita molestarse con ninguno de los métodos, pero si se encuentra en un escenario donde la paranoia sobre lo que realmente termina en el disco es algo bueno, debe hacer ambas llamadas según las instrucciones.


Anexo en 2018.

Tenga en cuenta que los discos con mecanismos de caché ahora son mucho más comunes que en 2013, por lo que ahora hay aún más niveles de almacenamiento en caché y búferes involucrados. Yo asumo estos tampones estarán a cargo de las llamadas de sincronización / ras así, pero no se sabe muy bien.

Lasse V. Karlsen
fuente
10
Cuando uso la with file('blah') as fd: #dostuffconstrucción, sé que garantiza el cierre del descriptor de archivo. ¿También se descarga o se sincroniza?
Marcin
3
@ Marcin: Se descarga, pero NO se sincroniza.
Alex I
8
fsyncEs necesario para la atomicidad. no puede esperar cerrar un archivo, volver a abrirlo y encontrar su contenido sin un fsyncen el medio. A menudo funciona, pero no funciona en Linux con ext4 y las opciones de montaje predeterminadas, por ejemplo. Tampoco fsyncse garantiza que realmente gire la plancha con imán en las bandejas, ya que 1: fsync se puede deshabilitar (en modo portátil) y 2: el almacenamiento en búfer interno del disco duro podría no recibir instrucciones de descarga.
v.oddou
1
¿Hay alguna manera de vaciar el búfer de un sistema operativo para todos los archivos, si el archivo está escrito por otro proceso?
Nacht
1
fsync es relativamente caro. En general, no está escribiendo un software de misión crítica que necesita un 100% de cumplimiento con ACID y durabilidad para el acceso al disco, y si lo hace, probablemente esté consciente de ello y debe conocer los pasos que puede seguir para obtener estas garantías . Llamar a fsync esperará a que ocurra el acceso físico al disco para escribir los datos en el disco, mientras que el vaciado y el cierre solo esperarán a que los datos se muevan a la memoria caché. La diferencia de velocidad es probablemente varios órdenes de magnitud.
Lasse V. Karlsen
10

Porque el sistema operativo puede no hacerlo. La operación de vaciado fuerza los datos del archivo a la memoria caché del archivo en la RAM, y desde allí el trabajo del sistema operativo es enviarlo al disco.

Ignacio Vazquez-Abrams
fuente
66
Tiene razón, pero actuallyes relativo aquí: si el dispositivo de destino tiene habilitado el almacenamiento en caché de escritura, es posible que los datos no hayan alcanzado los platos / chips reales cuando os.fsync()regrese.
Frédéric Hamidi
7

Vacía el búfer interno, lo que se supone que hace que el sistema operativo escriba el búfer en el archivo. [1] Python usa el almacenamiento en búfer predeterminado del sistema operativo a menos que lo configure de otra manera.

Pero a veces el sistema operativo aún elige no cooperar. Especialmente con cosas maravillosas como retrasos de escritura en Windows / NTFS. Básicamente, el búfer interno está enjuagado, pero el búfer del sistema operativo todavía lo mantiene. Por lo tanto, debe decirle al sistema operativo que lo escriba en el disco os.fsync()en esos casos.

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

Dan
fuente
0

Básicamente, flush () limpia su búfer de RAM, su poder real es que le permite continuar escribiendo en él después, pero no debe considerarse como la mejor / más segura función de escritura en archivo. Está vaciando su RAM para que lleguen más datos, eso es todo. Si desea asegurarse de que los datos se escriban en un archivo de forma segura, use close () en su lugar.

zA.
fuente