Używam logowania w Pythonie iz jakiegoś powodu wszystkie moje wiadomości pojawiają się dwukrotnie.
Mam moduł do konfiguracji logowania:
# 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 tę metodę, aby skonfigurować logowanie:
if __name__ == '__main__':
tom = Boy()
tom.configure_logging(LOG_FILENAME)
tom.buy_ham()
A potem, powiedzmy, moduł buy_ham zadzwoniłbym:
self.logger.info('Successfully able to write to %s' % path)
Z jakiegoś powodu wszystkie wiadomości pojawiają się dwukrotnie. Skomentowałem jeden z programów obsługi strumienia, wciąż to samo. Trochę dziwne, nie wiem, dlaczego tak się dzieje ... lol. Zakładając, że przegapiłem coś oczywistego.
Pozdrawiam, Victor
configure_logging()
nie jest wywoływana dwukrotnie (np. Też z konstruktora)? Czy tworzona jest tylko jedna instancja Boy ()?self.logger.handlers = [ch]
zamiast tego rozwiązałoby ten problem, chociaż najlepiej byłoby po prostu upewnić się, że nie uruchamiasz tego kodu dwukrotnie, na przykład używającif not self.logger
at the start.Odpowiedzi:
Dzwonisz
configure_logging
dwukrotnie (może w__init__
metodzieBoy
):getLogger
zwróci ten sam obiekt, aleaddHandler
nie sprawdzi, czy podobny handler został już dodany do loggera.Spróbuj prześledzić wywołania tej metody i wyeliminować jedną z nich. Lub skonfiguruj flagę
logging_initialized
zainicjowaną doFalse
w__init__
metodzieBoy
i zmień,configure_logging
aby nic nie robić, jeślilogging_initialized
takTrue
, i ustaw jąTrue
po zainicjowaniu rejestratora.Jeśli twój program tworzy kilka
Boy
instancji, będziesz musiał zmienić sposób, w jaki robisz rzeczy za pomocąconfigure_logging
funkcji globalnej dodającej moduły obsługi, aBoy.configure_logging
metodę tylko inicjalizującąself.logger
atrybut.Innym sposobem rozwiązania tego problemu jest sprawdzenie atrybutu handlers twojego loggera:
źródło
logger
użyta zmienna nie była tą, która została utworzona z jednej z moich klas, alelogger
zmienna obecna w pamięci podręcznej Python3 , a program obsługi był dodawany co 60 sekund przez skonfigurowany przeze mnie program AppScheduler. Tak, toif not logger.handlers
jest całkiem sprytny sposób na uniknięcie tego typu zjawiska. Dzięki za rozwiązanie, towarzyszu :)!Jeśli widzisz ten problem i nie dodajesz programu obsługi dwa razy, zobacz odpowiedź abarnert tutaj
Z dokumentów :
Tak więc, jeśli chcesz, aby niestandardowy program obsługi był włączony „test” i nie chcesz, aby jego komunikaty również trafiały do programu obsługi root, odpowiedź jest prosta: wyłącz
propagate
flagę:źródło
Program obsługi jest dodawany za każdym razem, gdy dzwonisz z zewnątrz. Spróbuj usunąć Handler po zakończeniu pracy:
źródło
logger.handlers.pop()
w Pythonie 2.7,Jestem nowicjuszem w Pythonie, ale to wydawało się działać dla mnie (Python 2.7)
źródło
W moim przypadku ustawiłbym,
logger.propagate = False
aby zapobiec podwójnemu drukowaniu.W poniższym kodzie, jeśli usuniesz
logger.propagate = False
, zobaczysz podwójne drukowanie.źródło
logger.propagate = False
było rozwiązaniem zapobiegającym podwójnemu logowaniu w aplikacji Flask hostowanej przez Waitress podczas logowania doapp.logger
instancji Flask .Wywołanie
logging.debug()
wywołań,logging.basicConfig()
jeśli nie ma zainstalowanych programów obsługi root. Działo się to w przypadku mnie w ramach testów, w których nie mogłem kontrolować kolejności uruchamiania przypadków testowych. Mój kod inicjalizacyjny instalował drugi. Domyślnie używa logging.BASIC_FORMAT, którego nie chciałem.źródło
Wygląda na to, że jeśli wypisujesz coś do rejestratora (przypadkowo), a następnie go skonfigurujesz, jest już za późno. Na przykład w moim kodzie miałem
Dostałbym coś takiego (ignorując opcje formatu)
i wszystko zostało dwukrotnie zapisane na standardowe wyjście. Uważam, że dzieje się tak, ponieważ pierwsze wywołanie
logging.warning
automatycznie tworzy nową procedurę obsługi, a następnie wyraźnie dodałem kolejną procedurę. Problem zniknął, gdy usunąłem przypadkowe pierwszelogging.warning
połączenie.źródło
Otrzymałem dziwną sytuację, w której dzienniki konsoli były podwojone, ale dzienniki moich plików nie. Po wielu kopaniu zrozumiałem.
Należy pamiętać, że pakiety stron trzecich mogą rejestrować loggery. Jest to coś, na co należy uważać (aw niektórych przypadkach nie można temu zapobiec). W wielu przypadkach kod strony trzeciej sprawdza, czy istnieje jakikolwiek root programy obsługi rejestrującego; a jeśli nie ma - rejestrują nowy program obsługi konsoli.
Rozwiązaniem tego problemu było zarejestrowanie mojego rejestratora konsoli na poziomie głównym:
źródło