2010-03-25 16 views
21

Bien. He completado mi primer programa python. Tiene alrededor de 1000 líneas de código. Durante el desarrollo me colocaron un montón de print declaraciones antes de ejecutar un comando con os.system() decir algo como,redirige las impresiones al archivo de registro

print "running command",cmd 
os.system(cmd) 

Ahora he completado el programa. Pensé en comentarlos pero sería más útil redirigir todas estas impresiones innecesarias (no puedo eliminar todas las declaraciones print, ya que algunas proporcionan información útil para el usuario) en un archivo de registro. Cualquier trucos o consejos.

+0

Creo fragmento de código elemental siempre por Michel va a cumplir mis requisitos ... gracias a todos –

Respuesta

31

Python que permite captura y asigna sys.stdout, como se mencionó, para hacer esto:

import sys 
old_stdout = sys.stdout 

log_file = open("message.log","w") 

sys.stdout = log_file 

print "this will be written to message.log" 

sys.stdout = old_stdout 

log_file.close() 
+10

También puede hacer - sys.stdout = sys .__ stdout__ - en lugar de usar old_stdout. –

+0

agradable, gracias. perder referencia a stdout sería desagradable – Michael

+0

Esto es un truco desordenado, pero ciertamente posible. Si ** usas **, reinicia 'sys.stdout' a su valor original en el bloque' finally' de 'try/finally'. –

1

Poner su propio archivo en sys.stdout le permitirá capturar el texto de salida a través de print.

+2

Esto es cierto pero horrible y no debe ser usado. –

30

Usted debe echar un vistazo a python logging module


EDIT: Código de ejemplo:

import logging 

if __name__ == "__main__": 
    logging.basicConfig(level=logging.DEBUG, filename="logfile", filemode="a+", 
         format="%(asctime)-15s %(levelname)-8s %(message)s") 
    logging.info("hello") 

Producir un archivo denominado "archivo de registro" con contenido:

2012-10-18 06:40:03,582 INFO  hello 
+0

+1 para el módulo de registro. Te da mucho más control que imprimir estados de cuenta. –

+9

¡Su solución de hecho no responde a la pregunta de "cómo redirigir la salida" en absoluto! Vaya a esa página - busque (en vano) cualquier indicio de cómo redirigir el registro a un archivo. La solución real está en la página de logging.config, pero te desafío a que la encuentres allí. http://onlamp.com/pub/a/python/2005/06/02/logging.html podría ser un mejor ejemplo. –

+2

@TomSwirly en la parte inferior de la página: un enlace a http://docs.python.org/library/logging.handlers.html#module-logging.handlers le ofrece una página donde se explica 'FileHandler' –

1

Puede redirigir a sys.stdout con cualquier objeto que tenga la misma interfaz que sys.stdout, en la escritura de ese objeto puede imprimir a la terminal y al archivo también. p.ej. ver esta receta http://code.activestate.com/recipes/119404-print-hook/

+0

Aunque es aplicable, esa receta es estilística, semántica y conceptualmente espantosa. –

+0

@Mike Graham, hey, escribí eso hace 8 años :), de todos modos, ¿por qué es eso tan horrible? –

+0

Evitaría usar algo así si pudiera hacerlo por un par de razones. Cambia un valor global ('sys.stdout') para uso local y puede tener efectos accidentales, lejanos e inesperados (esta es la razón por la que las personas evitan usar el estado global). Cuando está listo, restaura el valor a 'sys .__ stdout__', que puede y no ser lo que' sys.stdout' comenzó dependiendo de si alguien más estaba haciendo este tipo de truco. No tiene un uso tal que una excepción inesperada no dejará 'sys.stdout' pegado en un valor no deseado más adelante. –

2

Una forma sencilla para redirigir stdout y stderr usando el módulo de registro está aquí: How do I duplicate sys.stdout to a log file in python?

+0

Esa solución es repugnante y ni siquiera es totalmente aplicable (en el sentido de que escribe en stdout * y * un archivo; OP solo desea escribir en un archivo). –

+2

¿Podría explicar por qué es "repugnante"? Sé que redireccionar stdout es una mala idea, pero a veces vale la pena hacerlo: esta semana lo hice para ejecutar django en un servidor durante la noche para probarlo, y el comando runjanver de django se imprime en stdout. Además, compruebe su opinión antes de publicar porque la solución en cuestión _no_ escribe en stdout. Acabo de probarlo de nuevo. – blokeley

+0

Esto es repugnante porque usa globales.Esto significa que cuando lee 'print foo' no hace lo que espera sin leer dónde se cambió el global, que puede que ni siquiera esté en el mismo archivo que la declaración de impresión. Es inmodular porque muchas cosas no pueden hacer esto sanamente. Incluso reconoces que es una mala idea. Cuando algo debe imprimirse en stdout pero desea redirigirlo, hay herramientas para esto (como '>' en el shell); cuando algo debe escribirse en un lugar distinto de stdout, debe hacer que su código escriba ahí. –

8
  • La próxima vez, usted será más feliz si en lugar de utilizar print declaraciones en todo lo que uso el módulo logging desde el principio. Proporciona el control que desea y puede hacer que escriba en stdout mientras esté donde usted lo desee.

  • Muchas personas aquí han sugerido la redirección de stdout. Esta es una solución fea. Muta un global y, lo que es peor, lo muta para el uso de este módulo. Preferiría hacer una expresión regular que cambie todos print foo a print >>my_file, foo y establecer my_file en stdout o en un archivo real de mi elección.

    • Si tiene cualquier otra parte de la aplicación que realidad dependen de la escritura a la salida estándar (o alguna vez en el futuro, pero no se sabe todavía), esto les rompe. Incluso si no lo haces, parece que leer tu módulo parece que hace una cosa cuando realmente hace otra si te perdiste una pequeña alineación.
    • La impresión de Chevron es bastante fea, pero no es tan fea como el cambio temporal de sys.stdout para el proceso.
    • Técnicamente hablando, un reemplazo de expresiones regulares no es capaz de hacer esto bien (por ejemplo, podría hacer falsos positivos si está dentro de un literal de cadena multilínea). Sin embargo, es apto para funcionar, solo fíjate.
  • os.system es casi siempre inferior a utilizar el módulo subprocess. El último no necesita invocar el shell, no pasa señales de una manera que generalmente no es deseada, y puede usarse de una manera no bloqueante.

0

Puede crear un archivo de registro y prepararlo para la escritura. A continuación, crear una función:

def write_log(*args): 
    line = ' '.join([str(a) for a in args]) 
    log_file.write(line+'\n') 
    print(line) 

y luego reemplazar su impresión) nombre de la función (con write_log()

Cuestiones relacionadas