2011-07-18 12 views
36

Używam rejestrowania w języku Python i z jakiegoś powodu wszystkie moje wiadomości pojawiają się dwa razy.wiadomości dziennika pojawiające się dwukrotnie przy logowaniu w języku Python

Mam moduł do konfigurowania rejestrowania:

# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting. 
def configure_logging(self, logging_file): 
    self.logger = logging.getLogger("my_logger") 
    self.logger.setLevel(logging.DEBUG) 
    self.logger.propagate = 0 
    # Format for our loglines 
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 
    # Setup console logging 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    ch.setFormatter(formatter) 
    self.logger.addHandler(ch) 
    # Setup file logging as well 
    fh = logging.FileHandler(LOG_FILENAME) 
    fh.setLevel(logging.DEBUG) 
    fh.setFormatter(formatter) 
    self.logger.addHandler(fh) 

Później, nazywam ten sposób skonfigurować rejestrowania:

if __name__ == '__main__': 
    tom = Boy() 
    tom.configure_logging(LOG_FILENAME) 
    tom.buy_ham() 

a następnie w ciągu powiedzmy, moduł buy_ham, Nazwałbym :

self.logger.info('Successfully able to write to %s' % path) 

I z jakiegoś powodu wszystkie wiadomości pojawiają się dwa razy. Skomentowałem jedną z funkcji obsługi strumienia, wciąż to samo. Trochę dziwnego, nie wiem, dlaczego tak się dzieje ... lol. Zakładając, że przegapiłem coś oczywistego.

Cheers, Victor

+0

Czy na pewno funkcja 'configure_logging()' nie jest wywoływana dwukrotnie (np. również z konstruktora)? Czy utworzono tylko jedno wystąpienie Boy()? –

Odpowiedz

60

Telefonujesz configure_logging dwukrotnie (być może w metodzie __init__ z Boy): getLogger zwróci ten sam obiekt, ale addHandler nie sprawdza, czy podobna obsługi został już dodany do rejestratora .

Spróbuj śledzić połączenia do tej metody i wyeliminować jedną z nich. Lub ustawić flagę logging_initialized zainicjowany do False w sposobie Boy__init__ i zmienić configure_logging robić nic, jeśli logging_initialized jest True i ustawić go do True po tym, jak zainicjowany rejestratora.

Jeśli program tworzy kilka Boy instancji, musisz zmienić sposób robienia rzeczy z globalnym configure_logging funkcji, dodając teleskopowe, a metoda Boy.configure_logging tylko inicjowanie atrybut self.logger.

Innym sposobem rozwiązania jest to poprzez sprawdzenie koparki cechą rejestratora:

logger = logging.getLogger('my_logger') 
if not logger.handlers: 
    # create the handlers and call logger.addHandler(logging_handler) 
+1

Tak, miałeś rację - głupi mnie. Nazwałem to w __init__, a także wyraźnie w innym miejscu. Lol. Dzięki =). – victorhooi

+0

Dzięki. Twoje rozwiązanie uratowało mnie dzisiaj. – Tammy

+1

W moim przypadku pojawiły się one 6 razy. Podejrzewałem, że ponieważ zadeklarowałem ten sam typ rejestratora w 6 oop klasach – answerSeeker

5

Handler jest dodawany za każdym razem nawiązywać połączenia z zewnątrz. Spróbuj Removeing ​​Handler po zakończeniu swojej pracy:

self.logger.removeHandler(ch) 
+0

Użyłem 'logger.handlers.pop()' w python 2.7, czy lei – radtek

2

Jestem początkujących Python, ale to wydawało się działać dla mnie (Python 2.7)

while logger.handlers: 
    logger.handlers.pop() 
1

Jeśli widzisz ten problem i ty nie jesteś dodanie obsługi dwukrotnie następnie zobaczyć odpowiedź abarnert za here

z docs:

Uwaga: Jeśli dołączasz program obsługi do rejestratora i jednego lub więcej jego przodków, może on wysyłać ten sam rekord wiele razy. Ogólnie rzecz biorąc, użytkownik nie musi podłączać programu obsługi do więcej niż jednego programu rejestrującego - jeśli użytkownik podłączy go do odpowiedniego rejestratora, który jest najwyższy w hierarchii rejestrów , zobaczy wszystkie zdarzenia zarejestrowane przez wszystkie rejestratory potomne , pod warunkiem, że ich ustawienie propagacji jest ustawione na True.Wspólnym scenariuszem jest dołączanie procedur obsługi tylko do głównego programu rejestrującego, a do niech propagacja zajmie się resztą.

Tak więc, jeśli chcesz obsługi niestandardowych na „test”, a ty nie chcesz jej wiadomości również zamiar obsługi korzeniowego, odpowiedź jest prosta: należy wyłączyć jego banderą propagować:

rejestratora .propagate = False

Powiązane problemy