2012-03-22 19 views
15

Estoy ejecutando una prueba, y descubrí que el archivo realmente no se escribe hasta que controlo C para abortar el programa. ¿Alguien puede explicar por qué sucedería eso?¿Cómo es que un archivo no se escribe hasta que dejo el programa?

Esperaba que escribiera al mismo tiempo, por lo que pude leer el archivo en el medio del proceso.

import os 
from time import sleep 

f = open("log.txt", "a+") 
i = 0 
while True: 
    f.write(str(i)) 
    f.write("\n") 
    i += 1 
    sleep(0.1) 
+0

Re: "explicar por qué", véase http://stackoverflow.com/questions/ 1450551/buffer-io-vs-unbuffered-io –

Respuesta

49

Escribir en el disco es lento, por lo que muchos programas almacenan escrituras en grandes fragmentos que escriben todo a la vez. Esto se llama buffering, y Python lo hace automáticamente cuando abre un archivo.

Cuando escribe en el archivo, en realidad está escribiendo en un "búfer" en la memoria. Cuando se llena, Python lo escribirá automáticamente en el disco. Se puede decir que "escribir todo en la memoria intermedia en el disco ahora" con

f.flush() 

Esto no es absolutamente toda la historia, porque el sistema operativo probablemente amortiguar escribe así. Se puede decir que para escribir el buffer del archivo con

os.fsync(f.fileno()) 

Por último, se puede decir que no Python para amortiguar un archivo en particular con open(f, "w", 0) o sólo para mantener un buffer de 1 línea con open(f,"w", 1). Naturalmente, esto ralentizará todas las operaciones en ese archivo, porque las escrituras son lentas.

+0

+1 realmente informativo – twneale

+4

Tenga en cuenta que 'fsync()' gratuitos son la pesadilla de las personas con computadoras portátiles con discos giratorios que se preocupan por la duración de la batería. No necesita llamar a 'fsync()' para que el contenido sea visible para otros programas; está más cerca de ser sobre la visibilidad después de un reinicio inesperado (aunque tampoco necesariamente es una condición suficiente). –

+0

@CharlesDuffy: 'No necesita llamar a fsync() para que el contenido sea visible para otros programas': ¿por qué? Creo que si su programa no está terminado y otros programas leen el archivo, su contenido podría no actualizarse. –

5

Necesita f.close() para vaciar el búfer de escritura de archivo al archivo. O bien, en su caso, es posible que solo desee hacer un f.flush(); os.fsync(); para poder seguir bucles con el manejador de archivo abierto.

No se olvide de import os.

+0

... o 'f.flush()' –

+1

De hecho, pero esto no garantiza una completa escritura en el disco sin un os.fsync() – deed02392

+1

No todo el camino al disco , pero si es visible para otros programas, eso es lo que está pidiendo aquí. os.fsync() es costoso, y no debe usarse a menos que sepa que realmente lo desea (y, por lo general, tiene una manera para que el usuario lo desactive). Tenga en cuenta que incluso la mayoría de las bases de datos tienen una forma de desactivar fsync: a veces el usuario * quiere * arriesgarse a dañar los datos para acelerar las cosas. –

1

Usted tendrá que echa un vistazo a file.flush() - a pesar de tener en cuenta que esto podría no escribir los datos en el disco, para citar:

Nota: flush() no necesariamente escribir los datos del archivo de disco. Use flush() seguido de os.fsync() para garantizar este comportamiento.

Cierre el archivo (file.close()) también se asegurará de que los datos se escriben - usando with lo hará de forma implícita, y en general es una mejor opción para más legibilidad y claridad - por no hablar de la solución de otros problemas potenciales.

0

Este es un logotipo de Windows. Si agrega un .close() explícito cuando haya terminado con el archivo, aparecerá en el explorador en ese momento. Incluso el solo enjuagarlo podría ser suficiente (no tengo una caja de Windows a mano para probar). Pero básicamente f.write en realidad no escribe, simplemente se agrega al buffer de escritura - hasta que el buffer se vacíe no lo verá.

En Unix los archivos generalmente aparecerán como un archivo de 0 bytes en esta situación.

0

File Handler to be tirado.

f.flush() 
0

el archivo no se escriben, como el búfer de salida no está siendo enrojeció hasta que la recolección de basura entra en vigor, y vacía el búfer de E/S (más que probable llamando f.close()).

O bien, en su ciclo, puede llamar al f.flush() seguido de os.fsync(), como se documentó en here.

f.flush() 
os.fsync() 

dicho todo esto, si alguna vez planea compartir los datos en ese archivo con otras partes de su código, lo recomiendo encarecidamente utilizar un objeto StringIO.

1

usted tiene que forzar la escritura, por lo que yo uso las siguientes líneas para asegurarse de que un archivo está escrito:

# Two commands together force the OS to store the file buffer to disc 
    f.flush() 
    os.fsync(f.fileno()) 
Cuestiones relacionadas