2013-08-05 20 views
5

Desidero registrare i messaggi di un nome specifico del registratore, di un certo livello e superiore (ad esempio INFO e successivi) a un gestore di registri specifico, ad esempio un gestore di file, mentre ancora ottenere tutti i messaggi di registro sulla console. Python è la versione 2.7.Registrazione Python: propagare i messaggi di livello inferiore al livello attuale del logger

Quello che ho cercato fino ad ora è stato quello di creare due taglialegna:

  • Un logger principale
  • Un registratore di nome

Per il logger principale, ho attaccato un logging.StreamHandler, e impostare il registro livello a logging.DEBUG.

Quindi ho collegato un gestore al registratore denominato e impostato il livello su logging.INFO per quel registratore.

Quando ora chiamo il mio modulo, che utilizza il logger nominato, non ottengo più i log DEBUG propagati al logger root.

Nota: l'ExtraLogger ha uno StreamHandler qui per dimostrare il problema. Nel mio codice di produzione userei un FileHandler

import logging 

def do_logging(turn): 
    logger = logging.getLogger('extra') 
    logger.info('some info turn %d' % turn) 
    logger.debug('this is debug fudge turn %d' % turn) 

rootLogger = logging.getLogger() 
handler = logging.StreamHandler() 
rootFormatter = logging.Formatter('root - %(levelname)s: %(msg)s') 
handler.setFormatter(rootFormatter) 
rootLogger.addHandler(handler) 
rootLogger.setLevel(logging.DEBUG) 

do_logging(1) 

extraLogger = logging.getLogger('extra') 
extraHandler = logging.StreamHandler() 
extraFormatter = logging.Formatter('extra - %(levelname)s: %(msg)s') 
extraHandler.setFormatter(extraFormatter) 
extraLogger.addHandler(extraHandler) 
extraLogger.setLevel(logging.INFO) 

do_logging(2) 

uscita effettiva:

root - INFO: some info turn 1 
root - DEBUG: this is debug fudge turn 1 
extra - INFO: some info turn 2 
root - INFO: some info turn 2 

uscita che vorrei avere:

root - INFO: some info turn 1 
root - DEBUG: this is debug fudge turn 1 
extra - INFO: some info turn 2 
root - INFO: some info turn 2 
root - DEBUG: this is debug fudge turn 2 

Ho il sospetto che una consuetudine Filter sarebbe utile in questo caso, ma non so come ...

risposta

4

si potrebbe usare robert's LevelFilter come questo:

# Put the Filter on the Handler so only INFO and higher is handled 
extraHandler.addFilter(LevelFilter(logging.INFO)) 

# Let the Logger process everything (so it can propagate records to root) 
extraLogger.setLevel(logging.DEBUG) 

import logging 

class LevelFilter(logging.Filter): 
    """ 
    https://stackoverflow.com/a/7447596/190597 (robert) 
    """ 
    def __init__(self, level): 
     self.level = level 

    def filter(self, record): 
     return record.levelno >= self.level 

def do_logging(turn): 
    logger = logging.getLogger('extra') 
    logger.info('some info turn %d' % turn) 
    logger.debug('this is debug fudge turn %d' % turn) 

rootLogger = logging.getLogger() 
handler = logging.StreamHandler() 
rootFormatter = logging.Formatter('root - %(levelname)s: %(msg)s') 
handler.setFormatter(rootFormatter) 
rootLogger.addHandler(handler) 
rootLogger.setLevel(logging.DEBUG) 
do_logging(1) 

extraLogger = logging.getLogger('extra') 
extraHandler = logging.StreamHandler() 
extraFormatter = logging.Formatter('extra - %(levelname)s: %(msg)s') 
extraHandler.setFormatter(extraFormatter) 
extraLogger.addHandler(extraHandler) 

# Put the Filter on the Handler so only INFO and higher is handled 
extraHandler.addFilter(LevelFilter(logging.INFO)) 

# Handle everything (so it can propagate to root) 
extraLogger.setLevel(logging.DEBUG) 
do_logging(2) 
+1

Funziona bene, grazie mille. Sembra che dopo che un logger ha cancellato le voci di registro basate sul meccanismo di livello nudo, non le propagherà più. Qui ciò viene risolto impostando il livello di registro in basso, ma solo i messaggi di registro del livello desiderato, che consente la propagazione delle voci di registro di livello inferiore. – trapicki

+1

Sì, è corretto. C'è un [bel diagramma di flusso nei documenti] (http://docs.python.org/2/howto/logging.html#logging-flow) che stabilisce il giusto modello mentale. Non si desidera che il filtro collegato al registratore rifiuti il ​​record perché non raggiunge mai il passaggio di propagazione. – unutbu

+1

Oh, c'è una grande differenza se un filtro è collegato a un gestore o un logger ... Il sottocampo _handler sembra fuorviante: _Stop_ non interrompe l'elaborazione, ritorna solo da quel gestore senza emettere qualcosa, e il flusso passerebbe il prossimo gestore, o sbaglio, @unutbu? – trapicki

0

C'è un metodo nella classe logger chiamato "propagare" che sembra fare ciò che si chiede: http://docs.python.org/2/library/logging.html#logger-objects

+0

AFAIU 'Logger.propagate 'è una proprietà booleana che controlla se la propagazione avviene del tutto. Ho provato a giocherellare con quello, ma sembra che le voci di registro siano scartate in base al livello e quindi non si propagano comunque al logger root. – trapicki

Problemi correlati