¿Con qué frecuencia Python va a un archivo?

228
  1. ¿Con qué frecuencia Python va a un archivo?
  2. ¿Con qué frecuencia Python va al stdout?

No estoy seguro acerca de (1).

En cuanto a (2), creo que Python se enrojece después de cada nueva línea. Pero, si sobrecarga stdout para estar en un archivo, ¿se descarga tan a menudo?

Tim McJilton
fuente

Respuestas:

332

Para las operaciones de archivo, Python utiliza el almacenamiento en búfer predeterminado del sistema operativo a menos que lo configure de otra manera. Puede especificar un tamaño de búfer, sin búfer o con búfer de línea.

Por ejemplo, la función abierta toma un argumento de tamaño de búfer.

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

"El argumento de almacenamiento en búfer opcional especifica el tamaño de búfer deseado del archivo:"

  • 0 significa sin búfer,
  • 1 significa línea tamponada,
  • cualquier otro valor positivo significa usar un buffer de (aproximadamente) ese tamaño.
  • Un almacenamiento en búfer negativo significa usar el valor predeterminado del sistema, que generalmente está protegido en línea para dispositivos tty y totalmente protegido para otros archivos.
  • Si se omite, se utiliza el valor predeterminado del sistema.

código:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)
Corey Goldberg
fuente
23
+1 para la parte "línea tamponada". Eso es exactamente lo que estaba buscando y funciona a las mil maravillas.
rienda
2
Usando Python 3.4.3 cuando lo hago open('file.txt', 'w', 1), obtengo el búfer de línea adecuado. Pero si hago algo más grande (que quería open('file.txt', 'w', 512)), amortigua el total io.DEFAULT_BUFFER_SIZEde 8192. ¿Es eso un error de Python, un error de Linux o un error ID10t?
Bruno Bronosky
¿Es posible cambiar el almacenamiento en búfer para las secuencias ya abiertas ? Digamos, ¿quiero stdouttener un buffer de línea independientemente de si es una consola o ser redirigido a un archivo?
Mikhail T.
1
@CharlieParker cuando llama write()a un identificador de archivo, la salida se almacena en la memoria intermedia y se acumula hasta que el búfer está lleno ... en ese momento el búfer se "vacía" (el contenido se escribe desde el búfer en el archivo). Puede vaciar explícitamente el búfer llamando al flush()método en un identificador de archivo.
Corey Goldberg
3
Tenga en cuenta que sin búfer (0) solo está disponible en modo binario y que la línea con búfer (1) solo está disponible en modo texto.
ZaydH
173

También puede forzar el vaciado del búfer a un archivo mediante programación con el flush()método.

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()

He encontrado esto útil al seguir un archivo de salida con tail -f.

kortina
fuente
54
De los documentos: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 la próxima vez enlace a dichos documentos. La única referencia que puedo encontrar es de github.com/jprzywoski/python-reference/blob/master/source/docs/… y no sé quién es.
Bruno Bronosky
55
@Bruno Bronosky Buen punto. Docs: Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
lo que me confunde es lo que el término flushingsignifica. ¿Por qué lo necesitamos? ¿Para qué sirve? ¿Por qué debería importarme?
Charlie Parker
@CharlieParker cuando escribe, escribe en una copia (parte del) archivo en la RAM, que podría no guardarse en el disco por un tiempo. Mejora el rendimiento, pero puede significar la pérdida de datos si esa copia nunca se escribe (disco eliminado, fallas del sistema operativo, etc.). flush () le dice a Python que escriba de inmediato ese búfer en el disco. (Entonces, os.fsync () le dice al sistema operativo que también lo haga. Hay muchas capas de buffers ...)
Rena
13

No sé si esto también se aplica a Python, pero creo que depende del sistema operativo que esté ejecutando.

En Linux, por ejemplo, la salida al terminal vacía el búfer en una nueva línea, mientras que para la salida a los archivos solo se vacía cuando el búfer está lleno (por defecto). Esto se debe a que es más eficiente vaciar el búfer menos veces y es menos probable que el usuario se dé cuenta si la salida no se vacía en una nueva línea en un archivo.

Es posible que pueda enjuagar automáticamente la salida si eso es lo que necesita.

EDITAR: creo que de esta manera se enjuagará automáticamente en Python (desde aquí )

#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
fuente
12

También puede verificar el tamaño predeterminado del búfer llamando al atributo DEFAULT_BUFFER_SIZE de solo lectura desde el módulo io.

import io
print (io.DEFAULT_BUFFER_SIZE)
N Randhawa
fuente
1
¡Gracias! Es bueno saber que Python lo establece como lo define el sistema operativo ... pero esto ayuda a descubrir lo que el sistema operativo define previamente.
Cometsong
2

Aquí hay otro enfoque, hasta el OP para elegir cuál prefiere.

Al incluir el código a continuación en el __init__archivo .py antes que cualquier otro código, los mensajes impresos printy cualquier error ya no se registrarán en Ableton's Log.txt sino para separar los archivos en su disco:

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

(para Mac, cambie #username#el nombre de su carpeta de usuario. En Windows, la ruta a su carpeta de usuario tendrá un formato diferente)

Cuando abre los archivos en un editor de texto que actualiza su contenido cuando se cambia el archivo en el disco (ejemplo para Mac: TextEdit no lo hace pero TextWrangler sí), verá que los registros se actualizan en tiempo real.

Créditos: este código fue copiado principalmente de los scripts de superficie de control liveAPI por Nathan Ramella

Mattijs
fuente