2010-03-25 4 views
21

OK. Ho completato il mio primo programma python. Ha circa 1000 righe di codice. Durante lo sviluppo ho messo un sacco di print dichiarazioni prima di eseguire un comando utilizzando os.system() dire qualcosa di simile,reindirizzare le stampe sul file di registro

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

ora ho completato il programma. Ho pensato di commentarli ma reindirizzare tutte queste stampe non necessarie (non riesco a rimuovere tutte le dichiarazioni print - dal momento che alcune forniscono informazioni utili per l'utente) in un file di registro sarà più utile? Eventuali trucchi o suggerimenti.

+0

Penso semplice frammento di codice fornito da Michel soddisferà le mie esigenze ... grazie a tutti –

risposta

31

Python consente di Cattura e assegna sys.stdout - come detto - per fare questo:

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

Puoi anche fare - sys.stdout = sys .__ stdout__ - invece di usare old_stdout. –

+0

carino, grazie. perdere il riferimento allo stdout sarebbe brutto – Michael

+0

Questo è un hack disordinato, ma certamente possibile. Se ** lo fai **, resetta 'sys.stdout' al suo valore originale nel blocco' finally' di un 'try/finally'. –

1

Mettere il proprio file come in sys.stdout vi permetterà di catturare l'output del testo tramite print.

+2

Questo è vero ma terribile e non dovrebbe essere usato. –

30

Si dovrebbe dare un'occhiata a python logging module


EDIT: Codice di esempio:

import logging 

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

Produrre un file denominato "logfile" con i contenuti:

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

+1 per il modulo di registrazione. Ti dà via più controllo rispetto alle dichiarazioni di stampa. –

+9

La tua soluzione in realtà non risponde affatto alla domanda "come reindirizzare l'output"? Vai a quella pagina - cerca (invano) per qualsiasi suggerimento su come reindirizzare la registrazione in un file. La soluzione effettiva è nella pagina per logging.config, ma non posso sfidarlo a trovarlo lì. http://onlamp.com/pub/a/python/2005/06/02/logging.html potrebbe essere un esempio migliore. –

+2

@TomSwirly nella parte inferiore della pagina: un collegamento a http://docs.python.org/library/logging.handlers.html#module-logging.handlers fornisce una pagina in cui è spiegato 'FileHandler' –

1

È possibile reindirizzare sostituire sys.stdout con qualsiasi oggetto che abbia la stessa interfaccia di sys.stdout, in quella scrittura dell'oggetto è possibile stampare sul terminale e anche su file. per esempio. vedere questa ricetta http://code.activestate.com/recipes/119404-print-hook/

+0

Anche se applicabile, quella ricetta è stilisticamente, semanticamente e concettualmente terribile. –

+0

@Mike Graham, hey l'ho scritto 8 anni fa :), comunque perché è così terribile? –

+0

Eviterei di usare qualcosa del genere se potessi farlo per un paio di motivi. Cambia un valore globale ('sys.stdout') per uso locale e può avere effetti accidentali, lontani, inattesi (questo è il motivo per cui le persone evitano di usare lo stato globale). Quando ha finito, ripristina il valore di 'sys .__ stdout__', che può essere o non essere ciò che' sys.stdout' ha iniziato a dipendere se qualcun altro stava facendo questo tipo di trucco. Non ha un uso tale che un'eccezione inaspettata non lascerà 'sys.stdout' bloccato su un valore indesiderato in seguito. –

2

Un modo semplice per reindirizzare stdout e stderr utilizzando il modulo di registrazione è qui: How do I duplicate sys.stdout to a log file in python?

+0

Quella soluzione è disgustosa e nemmeno completamente applicabile (nel senso che scrive su stdout * e * un file; OP vuole solo scrivere su un file.) –

+2

Per favore, potresti spiegare perché questo è "disgustoso"? So che il reindirizzamento dello stdout è una cattiva idea, ma a volte vale la pena farlo: questa settimana l'ho fatto per eseguire django su un server durante la notte per il test, e il comando runServer di django stampa su stdout. Inoltre, si prega di verificare la propria opinione prima di postare perché la soluzione in questione non _non_ scrive su stdout. L'ho appena provato di nuovo. – blokeley

+0

Questo è disgustoso perché utilizza i globali.Ciò significa che quando si legge 'print foo' non fa ciò che ci si aspetta senza leggere dove è stato modificato il globale, che potrebbe non essere nemmeno nello stesso file dell'istruzione print. È impareggiabile perché molte cose non possono fare tutto così bene. Riconosci anche che è una cattiva idea. Quando qualcosa deve essere stampato su stdout ma tu vuoi reindirizzare, ci sono strumenti per questo (come '>' sulla shell); quando qualcosa dovrebbe essere scritto in un posto diverso dallo stdout, dovresti scrivere il tuo codice lì. –

8
  • La prossima volta, sarete più felici se invece di utilizzare print dichiarazioni a tutti di utilizzare il modulo logging dall'inizio. Fornisce il controllo che desideri e puoi farlo scrivere su stdout mentre è ancora dove lo vuoi.

  • Molte persone hanno suggerito di reindirizzare lo stdout. Questa è una brutta soluzione. Muta un globale e - cosa c'è di peggio - lo muta per l'uso di questo modulo. Presto eseguirò un'espressione regolare che cambia tutto print foo in print >>my_file, foo e imposta my_file in uno stdout o in un file effettivo di mia scelta.

    • Se avete altre parti dell'applicazione che realtà dipendono sulla scrittura su stdout (o mai sarà in futuro, ma non si sa ancora), questo li rompe. Anche se non lo fai, rende la lettura del tuo modulo come se facesse una cosa quando ne fa un'altra se ti sei perso una piccola linea in alto.
    • La stampa con la Chevron è piuttosto brutta, ma non è così brutta come cambiare temporaneamente sys.stdout per il processo.
    • In senso tecnico, una sostituzione di espressioni regolari non è in grado di eseguire questa operazione (ad esempio, potrebbe rendere falsi positivi se ci si trova all'interno di una stringa letterale a più righe). Tuttavia, è adatto a funzionare, basta tenerlo d'occhio.
  • os.system è quasi sempre inferiore al utilizzando il modulo subprocess. Quest'ultimo non ha bisogno di invocare la shell, non trasmette segnali in un modo che di solito non è voluto e può essere usato in modo non bloccante.

0

È possibile creare un file di registro e prepararlo per la scrittura. Quindi creare una funzione:

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

e quindi sostituire la stampa) nome della funzione (con write_log()