Al intentar escribir la salida estándar de un script de Python en un archivo de texto ( python script.py > log
), el archivo de texto se crea cuando se inicia el comando, pero el contenido real no se escribe hasta que finaliza el script de Python. Por ejemplo:
script.py:
import time
for i in range(10):
print('bla')
time.sleep(5)
se imprime en stdout cada 5 segundos cuando se llama con python script.py
, pero cuando llamo python script.py > log
, el tamaño del archivo de registro permanece cero hasta que finaliza el script. ¿Es posible escribir directamente en el archivo de registro, de modo que pueda seguir el progreso de la secuencia de comandos (por ejemplo, usando tail
)?
EDITAR Resulta que python -u script.py
hace el truco, no sabía sobre el almacenamiento en búfer de stdout.
Respuestas:
Esto sucede porque normalmente cuando el proceso STDOUT se redirige a algo diferente a un terminal, la salida se almacena en un búfer de tamaño específico del sistema operativo (quizás 4k u 8k en muchos casos). Por el contrario, cuando se envía a un terminal, STDOUT tendrá una línea de búfer o nada de búfer, por lo que verá la salida después de cada uno
\n
o para cada carácter.En general, puede cambiar el almacenamiento intermedio STDOUT con la
stdbuf
utilidad:Ahora, si es así
tail -F log
, debería ver cada salida de línea inmediatamente a medida que se genera.Alternativamente, el enjuague explícito del flujo de salida después de cada impresión debería lograr lo mismo. Parece que
sys.stdout.flush()
debería lograr esto en Python. Si está utilizando Python 3.3 o posterior, laprint
función también tiene unaflush
palabra clave que hace esto:print('hello', flush=True)
.fuente
python -u script.py
funciona. EDITAR Tantas respuestas a la vez, acepté la suya, ya que me señaló en la dirección del almacenamiento en búfer.--line-buffered
paragrep
, pero otros no.stdbuf
es la utilidad general de catchall para tratar con aquellos que no lo hacen.stdbuf -o0 python script.py > log
en este tipo de circunstancias determinadas?-oL
es un compromiso. En general, los buffers más grandes proporcionarán un mejor rendimiento al redirigir a algún lugar (menos llamadas al sistema y menos operaciones de E / S). Sin embargo, si es absolutamente necesario ver cada carácter a medida que sale, entonces sí,-o0
sería necesario.Esto debería hacer el trabajo:
Como Python almacenará el búfer
stdout
de forma predeterminada, aquí he utilizadosys.stdout.flush()
para vaciar el búfer.Otra solución sería utilizar el
-u
interruptor (sin búfer) depython
. Entonces, lo siguiente también lo hará:fuente
La variación sobre el tema del uso de la propia opción de python para la salida sin búfer sería usar
#!/usr/bin/python -u
como primera línea.Con
#!/usr/bin/env python
ese argumento extra no funcionará, así que, alternativamente, uno podría ejecutarloPYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt
o hacerlo en dos pasos:fuente
Deberías pasar
flush=True
a laprint
función:Según la documentación, de forma predeterminada,
print
no se aplica nada sobre el vaciado:Y la documentación de
sys
los strems dice:Si está atrapado con una versión antigua de python, debe llamar al
flush
método de lasys.stdout
transmisión:fuente
DigitalTrauma
dijo 10 horas antes. Deberías votar su publicación, no publicar la misma cosa de nuevo.print(flush=True)
fue agregada a esa respuesta después de la mía por un autor externo . Me parece de mal gusto extraer contenidos de mi respuesta para ponerlos en otro sin crédito. Decidí agregar mi respuesta únicamente porque ninguna respuesta mencionaba la forma más simple de lograr lo que el OP quería en las versiones más recientes de python, y agregué la "forma antigua" solo para completar. La próxima vez, verifique el historial de revisiones antes de comentar o votar a favor.__future__
la importación:from __future__ import print_function
. Pero sí, eso es solo por compatibilidad con Python 3