Chciałbym mieć loglevel TRACE (5) dla mojej aplikacji, ponieważ uważam, że debug()
to nie wystarczy. Poza log(5, msg)
tym nie jest tym, czego chcę. Jak mogę dodać niestandardowy loglevel do programu rejestrującego Python?
Mam mylogger.py
następującą treść:
import logging
@property
def log(obj):
myLogger = logging.getLogger(obj.__class__.__name__)
return myLogger
W swoim kodzie używam go w następujący sposób:
class ExampleClass(object):
from mylogger import log
def __init__(self):
'''The constructor with the logger'''
self.log.debug("Init runs")
Teraz chciałbym zadzwonić self.log.trace("foo bar")
Z góry dziękuje za twoją pomoc.
Edycja (8 grudnia 2016 r.): Zmieniłem zaakceptowaną odpowiedź na pfa's, czyli IMHO, doskonałe rozwiązanie oparte na bardzo dobrej propozycji Erica S.
źródło
logging.DEBUG_LEVEL_NUM = 9
aby mieć dostęp do tego poziomu debugowania wszędzie tam, gdzie importujesz rejestrator w swoim kodzie?DEBUG_LEVEL_NUM = 9
powinieneś zdefiniowaćlogging.DEBUG_LEVEL_NUM = 9
. W ten sposób będziesz mógł korzystać wlog_instance.setLevel(logging.DEBUG_LEVEL_NUM)
ten sam sposób, w jaki korzystałeś z right knowlogging.DEBUG
lublogging.INFO
logging.DEBUGV = DEBUG_LEVELV_NUM
ilogging.__all__ += ['DEBUGV']
Drugie nie jest strasznie ważne, ale pierwsze jest konieczne, jeśli masz jakiś kod, który dynamicznie dostosowuje poziom logowania i chcesz mieć możliwość zrobienia czegoś takiego jakif verbose: logger.setLevel(logging.DEBUGV)
`Przyjąłem odpowiedź „unikaj wyświetlania lambda” i musiałem zmodyfikować miejsce dodawania log_at_my_log_level. Widziałem również problem, który zrobił Paul "Nie sądzę, że to działa. Czy nie potrzebujesz loggera jako pierwszego argumentu w log_at_my_log_level?" To zadziałało dla mnie
źródło
__init__.py
i bądź szczęśliwy: DTypeError: not all arguments converted during string formatting
ale działa dobrze z *. (Python 3.4.3). Czy jest to problem z wersją Pythona, czy coś, czego mi brakuje?AttributeError: module 'logging' has no attribute 'debugv'
Łącząc wszystkie istniejące odpowiedzi z wieloma doświadczeniami dotyczącymi użytkowania, myślę, że opracowałem listę wszystkich rzeczy, które należy zrobić, aby zapewnić całkowicie bezproblemowe korzystanie z nowego poziomu. Poniższe kroki zakładają, że dodajesz nowy poziom
TRACE
z wartościąlogging.DEBUG - 5 == 5
:logging.addLevelName(logging.DEBUG - 5, 'TRACE')
musi zostać wywołane, aby nowy poziom został zarejestrowany wewnętrznie, tak aby można było do niego odwoływać się za pomocą nazwy.logging
siebie o konsystencji:logging.TRACE = logging.DEBUG - 5
.trace
należy dodać dologging
modułu. Należy zachowywać się jakdebug
,info
itptrace
należy dodać do aktualnie skonfigurowanej klasy programu rejestrującego. Ponieważ nie jest to w 100% gwarantowanelogging.Logger
, użyjlogging.getLoggerClass()
zamiast tego.Wszystkie kroki ilustruje poniższa metoda:
źródło
Oldest
, a z pewnością docenisz, że jest to najlepsza odpowiedź ze wszystkich!args
wlogForLevel
realizacji umyślne / wymagane?To dość stare pytanie, ale zająłem się tylko tym samym tematem i znalazłem sposób podobny do tych, o których już wspomniałem, który wydaje mi się nieco czystszy. Zostało to przetestowane na 3.4, więc nie jestem pewien, czy użyte metody istnieją w starszych wersjach:
źródło
get
isetLoggerClass
dokładnie robić i dlaczego są potrzebne?TRACE
poziom do domyślnej biblioteki rejestrowania. +1Kto rozpoczął złą praktykę korzystania z metod wewnętrznych (
self._log
) i dlaczego każda odpowiedź jest oparta na tym ?! Rozwiązaniem w Pythonie byłoby użycieself.log
zamiast tego, więc nie musisz majstrować przy żadnych wewnętrznych rzeczach:źródło
Łatwiej jest mi utworzyć nowy atrybut dla obiektu rejestrującego, który przekazuje funkcję log (). Myślę, że moduł rejestrujący zapewnia addLevelName () i log () z tego właśnie powodu. Dlatego nie są potrzebne żadne podklasy ani nowa metoda.
teraz
powinien działać zgodnie z oczekiwaniami.
źródło
_log
, a nielog
.Chociaż mamy już wiele poprawnych odpowiedzi, to moim zdaniem bardziej pytoniczne:
Jeśli chcesz użyć
mypy
w swoim kodzie, zaleca się dodanie,# type: ignore
aby pomijać ostrzeżenia przed dodawaniem atrybutu.źródło
logging.trace = partial(logging.log, logging.TRACE) # type: ignore
?Myślę, że będziesz musiał podklasować
Logger
klasę i dodać metodę o nazwie,trace
która w zasadzie wywołujeLogger.log
poziom niższy niżDEBUG
. Nie próbowałem tego, ale to jest to, co wskazują doktorzy .źródło
logging.getLogger
aby zwrócić swoją podklasę zamiast klasy wbudowanej.setLoggerClass(MyClass)
a potem zadzwonićgetLogger()
jak zwykle ...Wskazówki dotyczące tworzenia niestandardowego rejestratora:
_log
, używajlog
(nie musisz sprawdzaćisEnabledFor
)getLogger
, więc będziesz musiał ustawić klasę za pomocąsetLoggerClass
__init__
dla loggera klasy, jeśli nic nie przechowujeszPodczas wywoływania tego rejestratora użyj,
setLoggerClass(MyLogger)
aby ustawić go jako domyślny rejestratorgetLogger
Trzeba będzie
setFormatter
,setHandler
isetLevel(TRACE)
nahandler
i nalog
sam faktycznie SE Ten niski poziom śladuźródło
To zadziałało dla mnie:
Problem lambda / funcName został naprawiony w logger._log, jak wskazał @marqueed. Wydaje mi się, że użycie lambdy wygląda na nieco czystszą, ale wadą jest to, że nie może przyjmować argumentów słów kluczowych. Sam nigdy z tego nie korzystałem, więc nie ma co.
źródło
Z mojego doświadczenia wynika, że jest to pełne rozwiązanie problemu operacji ... aby uniknąć postrzegania "lambda" jako funkcji, w której emitowany jest komunikat, wejdź głębiej:
Nigdy nie próbowałem pracować z samodzielną klasą rejestratora, ale myślę, że podstawowa idea jest taka sama (użyj _log).
źródło
logger
jako pierwszego argumentulog_at_my_log_level
?Dodatek do przykładu Mad Physicists, aby uzyskać poprawną nazwę pliku i numer linii:
źródło
Bazując na przypiętej odpowiedzi, napisałem małą metodę, która automatycznie tworzy nowe poziomy logowania
config może coś takiego:
źródło
Jako alternatywę dla dodania dodatkowej metody do klasy Logger polecam użycie
Logger.log(level, msg)
metody.źródło
Jestem zmieszany; przynajmniej z Pythonem 3.5 po prostu działa:
wynik:
źródło
logger.trace('hi')
co moim zdaniem jest głównym celemW przypadku, gdyby ktoś chciał zautomatyzować sposób dynamicznego dodawania nowego poziomu logowania do modułu logowania (lub jego kopii), utworzyłem tę funkcję, rozszerzając odpowiedź @ pfa:
źródło
setattr
zamiast tego ...