2013-08-05 10 views
5

Chcę rejestrować komunikaty o określonej nazwie rejestratora, o określonym poziomie i wyższym poziomie (na przykład INFO i wyższym), do określonego programu obsługi dziennika, na przykład do obsługi plików, ale nadal pobieranie wszystkich komunikatów dziennika do konsoli. Python to wersja 2.7.Rejestrowanie w języku Python: propagowanie komunikatów o poziomie poniżej bieżącego poziomu rejestratora

Co próbowałem do tej pory było stworzenie dwóch rejestratorów:

  • Korzeń rejestrator
  • Nazwany rejestrator

Na rejestratorze korzeni, ja załączeniu logging.StreamHandler i ustaw dziennik poziom do logging.DEBUG.

Następnie podłączyłem program obsługi do określonego rejestratora i ustawiłem poziom na logging.INFO dla tego programu rejestrującego.

Kiedy teraz zadzwonię do mojego modułu, który używa nazwanego rejestratora, nie otrzymuję już logów DEBUG propagowanych do głównego rejestratora.

Uwaga: dodatkowy logger ma StreamHandler tutaj, aby pokazać problem. W moim kodu produkcyjnego bym użyć 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) 

Rzeczywista wyjściowa:

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 

wyjściowy, który chciałbym posiadać:

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 

Podejrzewam, że zwyczaj Filter byłoby pomocne w tym przypadku, ale nie wiem jak ...

Odpowiedz

4

Można użyć robert's LevelFilter tak:

# 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

Działa dobrze, dziękuję bardzo. Wygląda na to, że po tym, jak program rejestrujący odrzuci wpisy dziennika na podstawie mechanizmu gołego poziomu, nie będzie ich już propagował. Tutaj sprawdza się to, ustawiając niższy poziom dziennika, ale tylko komunikaty dziennika o pożądanym poziomie, co pozwala na rejestrację wpisów niższego poziomu. – trapicki

+1

Tak, zgadza się. Istnieje [dobry schemat przepływu w dokumentach] (http://docs.python.org/2/howto/logging.html#logging-flow), który określa właściwy model mentalny. Nie chcesz, aby filtr dołączony do rejestratora odrzucił rekord, ponieważ wtedy nigdy nie dostanie się do kroku propagacji. – unutbu

+1

O, jest duża różnica, jeśli filtr jest dołączony do programu obsługi lub rejestratora ... Podkartownik _handlera wydaje się wprowadzać w błąd: _Stop_ nie przestałby przetwarzać, po prostu wracał z tego programu obsługi bez emitowania czegoś, a przepływ byłby przekazywany następny handler, czy też się mylę, @unutbu? – trapicki

0

Jest to metoda w klasie rejestratora o nazwie "propagować", który wydaje się robić to, co pytasz: http://docs.python.org/2/library/logging.html#logger-objects

+0

AFAIU 'Logger.propagate 'jest boolowską właściwością, która kontroluje, czy propagacja ma miejsce w ogóle. Próbowałem z nimi manipulować, ale wydaje się, że wpisy w dzienniku są odrzucane na podstawie poziomu, a zatem i tak nie są propagowane do głównego rejestru. – trapicki

Powiązane problemy