Używam modułu rejestrowania Pythona i chciałbym wyłączyć komunikaty dziennika drukowane przez moduły innych firm, które importuję. Na przykład używam czegoś takiego:
logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)
To wyświetla moje komunikaty debugowania, kiedy robię logger.debug ("moja wiadomość!"), Ale również wypisuje komunikaty debugowania z dowolnego modułu, który importuję (na przykład żądania i wiele innych rzeczy).
Chciałbym widzieć tylko komunikaty dziennika z modułów, które mnie interesują. Czy można tak ustawić moduł logowania?
Idealnie chciałbym móc nakazać rejestratorowi, aby drukował komunikaty z „ModuleX, ModuleY” i ignorował wszystkie inne.
Przyjrzałem się następującym, ale nie chcę wyłączać / włączać logowania przed każdym wywołaniem zaimportowanej funkcji: logowanie - jak zignorować zaimportowane logi modułów?
__name__
r, ale nadal widzę logi z zaimportowanych modułów. Próbuję skonfigurować logowanie za pomocą pliku konfiguracyjnego ini. Co mam w tym celu zrobić?__name__
również nie działało dla mnie. Może dlatego, że używam samodzielnego skryptu, a nie „modułu”? Pomogło mi skonfigurowanie logowania dla zaimportowanych modułów (matpplotlib
w moim przypadku) za pośrednictwemlogging.getLogger("matplotlib").setLevel(logging.WARNING)
i dla mojego skryptu przezlogging.basicConfig
.logger.debug
zamiastlogging.debug
”. Łatwo popełnić błąd przy użyciu rejestrowania zamiast rejestratora, ale przywłaszcza sobie całą sprytną konfigurację, którą chcesz ustawić. Żyłem tym przez ostatnie kilka godzin!logger = logging.getLogger('package.my_module')
wywołania and your couldlogger.debug/warning
, bez konfigurowania poziomów logowania lub programów obsługi. Kiedy piszesz tam aplikację binarną , powinieneś zdecydować o poziomie dla różnych dzienników i programów obsługi. Biblioteki zawierające konfigurację rejestrowania zawsze będą stanowić problem.logging.getLogger(__name__)
zamiast tego użyli .Jeśli zamierzasz używać
logging
pakietu pythona , powszechną konwencją jest definiowanie programu rejestrującego w każdym module, który go używa.Robi to wiele popularnych pakietów Pythona, w tym
requests
. Jeśli pakiet używa tej konwencji, łatwo jest włączyć / wyłączyć rejestrowanie dla niego, ponieważ nazwa programu rejestrującego będzie taka sama jak nazwa pakietu (lub będzie dzieckiem tego rejestratora). Możesz nawet zarejestrować go w tym samym pliku, co inne rejestratory.logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) requests_logger = logging.getLogger('requests') requests_logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() handler.setLevel(logging.DEBUG) logger.addHandler(handler) requests_logger.addHandler(handler)
źródło
logging.basicConfig(...)
wszystkie loggery będą teraz wyświetlać wyjścielogging.lastResort
(zaczynając od Pythona 3.2, który jest stderr), jeśli nie podano żadnej funkcji obsługi lub ustawionej funkcji obsługi. Więc nie używaj go, bo i tak będziesz nadal otrzymywać wszystkie komunikaty dziennika.Nie jestem pewien, czy to jest właściwe, aby opublikować, ale utknąłem na długi czas i chciałem pomóc każdemu z tym samym problemem, ponieważ nie znalazłem go nigdzie indziej!
Otrzymywałem dzienniki debugowania z matplotlib, mimo że postępowałem zgodnie z dość prostą dokumentacją w zaawansowanym samouczku rejestrowania i rozwiązywaniu problemów . Inicjowałem mój logger w
main()
jednym pliku i importowałem funkcję do tworzenia wykresu z innego pliku (gdzie zaimportowałem matplotlib).U mnie zadziałało ustawienie poziomu matplotlib przed jego zaimportowaniem, a nie później, jak w przypadku innych modułów w moim głównym pliku. Wydawało mi się to sprzeczne z intuicją, więc jeśli ktoś ma wgląd w to, jak ustawić konfigurację dla loggera, który nie został jeszcze zaimportowany, byłbym ciekawy, jak to działa. Dzięki!
W moim głównym pliku:
import logging import requests logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) logging.getLogger('requests').setLevel(logging.DEBUG) def main(): ...
W moim
plot.py
pliku:import logging logging.getLogger('matplotlib').setLevel(logging.WARNING) import matplotlib.pyplot as plt def generatePlot(): ...
źródło
logger.DEBUG
powinno byćlogging.DEBUG
matplotlib
sięWARNING
po ja importowany moduł, ponieważ dodanie go przed importem dałoby niestrzępiącą błąd. Nadal mi to działało. Używammatplotlib==3.3.2
w Pythonie 3.7, jeśli to pomaga.Spowoduje to wyłączenie wszystkich istniejących programów rejestrujących, takich jak te utworzone przez zaimportowane moduły, przy jednoczesnym korzystaniu z głównego programu rejestrującego (i bez konieczności ładowania zewnętrznego pliku).
import logging.config logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': True, })
Pamiętaj, że musisz najpierw zaimportować wszystkie moduły, których nie chcesz rejestrować! W przeciwnym razie nie będą one traktowane jako „istniejące rejestratory”. Następnie wyłączy wszystkie rejestratory z tych modułów. Może to prowadzić do pominięcia ważnych błędów!
Aby uzyskać bardziej szczegółowe przykłady przy użyciu powiązanych opcji konfiguracji, zobacz https://gist.github.com/st4lk/6287746 , a tutaj jest (częściowo działający) przykład użycia YAML do konfiguracji z
coloredlog
biblioteką.źródło
request
przykład, ale nie zadziała, gdy zaimportowane moduły utworzą swoje loggery w swojej klasie, do której zadzwonisz później, tak jakAPScheduler
robi to podczas rozmowyBackgroundScheduler.BackgroundScheduler()
. Zobacz tutaj rozwiązanie: stackoverflow.com/a/48891485/2441026import logging.config
, nie tylko logowanie.@Bakuriu dość elegancko wyjaśnia funkcję. I odwrotnie, możesz użyć tej
getLogger()
metody, aby odzyskać i ponownie skonfigurować / wyłączyć niechciane programy rejestrujące.Chciałem też dodać
logging.fileConfig()
metodę akceptującą wywoływany parametr,disable_existing_loggers
który wyłączy wcześniej zdefiniowane rejestratory (tj. W zaimportowanych modułach).źródło
Możesz użyć czegoś takiego:
logging.getLogger("imported_module").setLevel(logging.WARNING) logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)
Spowoduje to ustawienie poziomu dziennika mojego własnego modułu na DEBUG, jednocześnie uniemożliwiając importowanemu modułowi korzystanie z tego samego poziomu.
Uwaga:
"imported_module"
można go zastąpićimported_module.__name__
(bez cudzysłowów) i"my_own_logger_name"
można go zastąpić,__name__
jeśli wolisz to zrobić.źródło
Miałem ten sam problem. Mam plik logging_config.py, który importuję do wszystkich innych plików py. W pliku logging_config.py ustawiam poziom logowania root loggera na ERROR (domyślnie jest to ostrzeżenie):
logging.basicConfig( handlers=[ RotatingFileHandler('logs.log',maxBytes=1000, backupCount=2), logging.StreamHandler(), #print to console ], level=logging.ERROR )
W innych modułach importuję logging_config.py i deklaruję nowy logger i ustawiam jego poziom na debugowanie:
W ten sposób wszystko, co loguję w moich plikach py, jest rejestrowane, ale rzeczy rejestrowane na poziomie debugowania i informacji przez zaimportowane moduły, takie jak urllib, request, boto3 itp. Nie są rejestrowane. Jeśli wystąpi jakiś błąd w tym module importu, jest on rejestrowany, ponieważ ustawiłem poziom rejestratorów głównych na ERROR.
źródło
Inną rzeczą do rozważenia jest właściwość propagate klasy Logger.
Na przykład biblioteka py-suds do obsługi wywołań mydła, nawet ustawiona na ERROR
logging.getLogger('suds.client').setLevel(logging.ERROR) logging.getLogger('suds.transport').setLevel(logging.ERROR) logging.getLogger('suds.xsdschema').setLevel(logging.ERROR) logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
logs loguje o module o nazwie sxbasics.py tworzenie dużej ilości logów
że ponieważ propagacja dzienników jest domyślnie ustawiona na True, a ustawienie to False, zamiast tego odzyskałem 514 MB dzienników.
import logging logging.getLogger("suds").propagate = False logging.getLogger('suds.client').setLevel(logging.ERROR) logging.getLogger('suds.transport').setLevel(logging.ERROR) logging.getLogger('suds.xsdschema').setLevel(logging.ERROR) logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
źródło
Po prostu zrobienie czegoś takiego rozwiązuje problem:
logging.config.dictConfig({'disable_existing_loggers': True,})
źródło
W moim przypadku jedyne, co pomogło, to wymuszenie
propagate
atrybutu niechcianego loggeraFalse
, tjlogging.getLogger("module").propagate = False
źródło