2010-09-26 18 views
7

Tengo un script de Python de ejecución prolongada que ejecuto desde la línea de comandos. El script escribe mensajes de progreso y resultados en el resultado estándar. Quiero capturar todo lo que el script escribe en la salida estándar en un archivo, pero también verlo en la línea de comando. Alternativamente, quiero que la salida vaya al archivo inmediatamente, así que puedo usar tail para ver el progreso. He intentado esto:¿Cómo escribir la salida del script en el archivo y la línea de comandos?

python MyLongRunngingScript.py | tee log.txt 

Pero no produce ningún resultado (solo ejecutar el script produce la salida esperada). ¿Alguien puede proponer una solución simple? Estoy usando Mac OS X 10.6.4.

Editar Estoy usando print para la salida en mi script.

Respuesta

16

Estás en el camino correcto, pero el problema es que el almacenamiento en memoria tampón de python.

Afortunadamente, existe una manera de decir que no a la memoria intermedia de salida:

python -u MyLongRunngingScript.py | tee log.txt 
+3

No se olvide de volver a dirigir el flujo de '' '' stderr'' a stdout'' si también desea capturar lo siguiente: '' python -u MyLongRunngingScript.py 2> & 1 | tee log.txt'' – stephenfin

1

Puede intentar ocasionalmente hacer sys.stdout.flush() en su secuencia de comandos y ejecutarlo nuevamente con tee. Cuando stdout se redirige a tee, es posible que se guarde en el búfer por más tiempo que si va directamente a un terminal.

2

El hecho de que no vea nada probablemente esté relacionado con el hecho de que se está produciendo el almacenamiento en búfer. Por lo tanto, solo obtendrá una salida cada 4 Ko de texto más o menos.

lugar, intentar algo como esto:

class OutputSplitter(object): 
    def __init__(self, real_output, *open_files): 
     self.__stdout = real_output 
     self.__fds = open_files 
     self.encoding = real_output.encoding 
    def write(self, string): 
     self.__stdout.write(string) # don't catch exception on that one. 
     self.__stdout.flush() 
     for fd in self.__fds: 
      try: 
       fd.write(string) 
       fd.flush() 
      except IOError: 
       pass # do what you want here. 
    def flush(self): 
     pass # already flushed 

luego decorar sys.stdout con esa clase con un código de esa manera:

stdout_saved = sys.stdout 
logfile = open("log.txt","a") # check exception on that one. 
sys.stdout = OutputSplitter(stdout_saved, logfile) 

De esa manera, cada salida (print incluido) es purgado a la salida estándar y al archivo especificado. Podría requerir ajustes porque no he probado esa implementación.

Por supuesto, se espera una penalización de rendimiento (la mayoría de las veces) al imprimir mensajes.

Cuestiones relacionadas