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.pyhace 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
\no para cada carácter.En general, puede cambiar el almacenamiento intermedio STDOUT con la
stdbufutilidad: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, laprintfunción también tiene unaflushpalabra clave que hace esto:print('hello', flush=True).fuente
python -u script.pyfunciona. EDITAR Tantas respuestas a la vez, acepté la suya, ya que me señaló en la dirección del almacenamiento en búfer.--line-bufferedparagrep, pero otros no.stdbufes la utilidad general de catchall para tratar con aquellos que no lo hacen.stdbuf -o0 python script.py > logen este tipo de circunstancias determinadas?-oLes 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í,-o0sería necesario.Esto debería hacer el trabajo:
Como Python almacenará el búfer
stdoutde forma predeterminada, aquí he utilizadosys.stdout.flush()para vaciar el búfer.Otra solución sería utilizar el
-uinterruptor (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 -ucomo primera línea.Con
#!/usr/bin/env pythonese argumento extra no funcionará, así que, alternativamente, uno podría ejecutarloPYTHONUNBUFFERED=1 ./my_scriipt.py > output.txto hacerlo en dos pasos:fuente
Deberías pasar
flush=Truea laprintfunción:Según la documentación, de forma predeterminada,
printno se aplica nada sobre el vaciado:Y la documentación de
syslos strems dice:Si está atrapado con una versión antigua de python, debe llamar al
flushmétodo de lasys.stdouttransmisión:fuente
DigitalTraumadijo 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