2012-02-17 9 views
19

Ho trovato un codice online che generalmente funziona, ma voglio usarlo più volte nello stesso programma (scrivere cose diverse su file diversi, mentre si sta ancora stampando sullo schermo tutto il tempo).Stampa su schermo e scrittura su un file allo stesso tempo

Vale a dire, quando si chiude, penso che sys.stdout si chiude, quindi la stampa non funziona e l'uso di questa classe fallisce di nuovo. Ho provato a reimportare sys e altre cose stupide, ma non riesco a farlo funzionare.

Ecco il sito, e il codice groups.google.com/group/comp.lang.python/browse_thread/thread/d25a9f5608e473af/

import sys 

class MyWriter: 

    def __init__(self, stdout, filename): 
     self.stdout = stdout 
     self.logfile = file(filename, 'a') 

    def write(self, text): 
     self.stdout.write(text) 
     self.logfile.write(text) 

    def close(self): 
     self.stdout.close() 
     self.logfile.close() 

writer = MyWriter(sys.stdout, 'log.txt') 
sys.stdout = writer 

print 'test' 
+0

Quando si chiude? Non vedo niente chiudersi lì. –

+0

Dovresti accettare la risposta, in realtà – gt6989b

risposta

83

Si sta tentando di riprodurre male qualcosa che è fatto molto bene dalla libreria standard Python; si prega di controllare il logging module.

Con questo modulo è possibile eseguire esattamente ciò che si desidera, ma in modo molto più semplice, standard ed estensibile. È possibile procedere come segue (questo esempio è un copia/incolla dal logging cookbook):

Let’s say you want to log to console and file with different message formats and in differing circumstances. Say you want to log messages with levels of DEBUG and higher to file, and those messages at level INFO and higher to the console. Let’s also assume that the file should contain timestamps, but the console messages should not. Here’s how you can achieve this:

import logging 

# set up logging to file - see previous section for more details 
logging.basicConfig(level=logging.DEBUG, 
        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', 
        datefmt='%m-%d %H:%M', 
        filename='/temp/myapp.log', 
        filemode='w') 
# define a Handler which writes INFO messages or higher to the sys.stderr 
console = logging.StreamHandler() 
console.setLevel(logging.INFO) 
# set a format which is simpler for console use 
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') 
# tell the handler to use this format 
console.setFormatter(formatter) 
# add the handler to the root logger 
logging.getLogger('').addHandler(console) 

# Now, we can log to the root logger, or any other logger. First the root... 
logging.info('Jackdaws love my big sphinx of quartz.') 

# Now, define a couple of other loggers which might represent areas in your 
# application: 

logger1 = logging.getLogger('myapp.area1') 
logger2 = logging.getLogger('myapp.area2') 

logger1.debug('Quick zephyrs blow, vexing daft Jim.') 
logger1.info('How quickly daft jumping zebras vex.') 
logger2.warning('Jail zesty vixen who grabbed pay from quack.') 
logger2.error('The five boxing wizards jump quickly.') 

When you run this, on the console you will see

root  : INFO  Jackdaws love my big sphinx of quartz. 
myapp.area1 : INFO  How quickly daft jumping zebras vex. 
myapp.area2 : WARNING Jail zesty vixen who grabbed pay from quack. 
myapp.area2 : ERROR The five boxing wizards jump quickly. 

and in the file you will see something like

10-22 22:19 root   INFO  Jackdaws love my big sphinx of quartz. 
10-22 22:19 myapp.area1 DEBUG Quick zephyrs blow, vexing daft Jim. 
10-22 22:19 myapp.area1 INFO  How quickly daft jumping zebras vex. 
10-22 22:19 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack. 
10-22 22:19 myapp.area2 ERROR The five boxing wizards jump quickly. 

As you can see, the DEBUG message only shows up in the file. The other messages are sent to both destinations.

This example uses console and file handlers, but you can use any number and combination of handlers you choose.

+3

+1 Risposta migliore in tutte le domande SO per l'accesso allo schermo e file –

+0

Amo questa risposta, ma non sono sicuro che questo fosse ciò che il poster originale stava chiedendo. –

+0

Quando replicando esattamente il codice di cui sopra, dopo 'logging.info ('gazze amore mio grande Sfinge di quarzo.')' ottengo il seguente errore: ... file "C: \ Anaconda2 \ lib \ logging \ __ init__.py ", riga 467, nel formato record.asctime = self.formatTime (record, self.datefmt) File" C: \ Anaconda2 \ lib \ logging \ __ init__.py ", riga 425, in formatTime s = time.strftime (datefmt, ct) ValueError: stringa di formato non valida Qualcuno può aiutare? – riccio777

1

Rimuovere la riga che sta facendo quello che in modo esplicito che dici don Non voglio: la prima riga di close(), che chiude lo stdout.

0

That is to say, when it closes, I think sys.stdout closes, so printing at all, and using this class again fails. I tried reimporting sys, and other dumb stuff, but I can't get it to work.

per rispondere alla tua domanda , non dovresti chiudere stdout. L'interprete python apre stdout, stdin e stderror all'avvio. Per far funzionare la stampa, l'interprete richiede che stdout sia aperto. Reimporting sys non fa nulla dopo che un modulo è stato caricato. Dovresti ricaricare il modulo. In questo caso particolare, non sono sicuro che un ricaricamento risolverà il problema poiché sys.stdout consente a stdout di essere usato come oggetto file.

Inoltre, penso che si sia verificato un errore nel codice che potrebbe causare l'interruzione di stampa a . Nella riga 2 si assegna un oggetto MyWriter a sys.stdout. Ciò può chiudere lo stdout quando il garbage collector elimina l'oggetto file stdout inutilizzato.

writer = MyWriter(sys.stdout, 'log.txt') 
sys.stdout = writer 
4

facile peasy con Python 3.3 e superiori

A partire da Python 3.3, così facendo è diventato molto più facile dal momento che logging.basicConfig ora accetta l'argomento handlers =.

import logging 

level = logging.INFO 
format = ' %(message)s' 
handlers = [logging.FileHandler('filename.log'), logging.StreamHandler()] 
logging.basicConfig(level = level, format = format, handlers = handlers) 

logging.info('Hey, this is working!') 

Nota però, che alcuni moduli Python possono anche essere la pubblicazione di messaggi di registrazione al livello INFO.

È qui che viene portata di mano per create a custom logging level, chiamato ad esempio OK, 5 livelli sopra il livello di default INFO e 5 livelli al di sotto del livello predefinito WARNING.

Problemi correlati