2008-12-30 11 views
45

W Django, mam rejestratory w całym miejscu, obecnie z zakodowanymi nazwami.Nazewnictwo rejestratorów Python

Do rejestrowania na poziomie modułu (tj. W module funkcji widoku) mam ochotę to zrobić.

log = logging.getLogger(__name__) 

do logowania klasa poziomu (czyli w klasie __init__ metody) mam ochotę to zrobić.

self.log = logging.getLogger("%s.%s" % (
    self.__module__, self.__class__.__name__)) 

Szukam drugiej opinii, zanim przejdę do kilkudziesięciu wystąpień getLogger("hard.coded.name").

Czy to zadziała? Ktoś inny nazywał swoje rejestratory tymi samymi niewyobrażalnymi metodami?

Co więcej, powinienem się zepsuć i napisać dekorator klasy dla tej definicji dziennika?

+0

Jestem ciekawy: dlaczego miałbyś chcieć loginu na poziomie klasy? – glarrain

Odpowiedz

65

ja zazwyczaj nie używają lub znaleźć potrzebę rejestratorów poziomie klasy, ale ja trzymam modułów na kilka klas w większości. Prosty:

import logging 
LOG = logging.getLogger(__name__) 

Na górze modułu i późniejsze:

LOG.info('Spam and eggs are tasty!') 

z dowolnego miejsca w pliku zazwyczaj dostaje mnie, gdzie chcę być. Dzięki temu unika się potrzeby wszędzie w jednym miejscu, co przeszkadza mi zarówno z perspektywy "put-it-in-co-class", i sprawia, że ​​jestem o 5 znaków bliżej linii 79-znakowych, które pasują.

Zawsze można użyć pseudo-klasy dekoratora:

>>> import logging 
>>> class Foo(object): 
...  def __init__(self): 
...    self.log.info('Meh') 
... 
>>> def logged_class(cls): 
...  cls.log = logging.getLogger('{0}.{1}'.format(__name__, cls.__name__)) 
... 
>>> logged_class(Foo) 
>>> logging.basicConfig(level=logging.DEBUG) 
>>> f = Foo() 
INFO:__main__.Foo:Meh 
+7

Interesujące podejście ...Wydaje mi się, że zbyt długo spędziłem z Javą. Rejestrowanie na poziomie modułu może być dokładnie tym, co zalecił lekarz. –

+7

Jest jeden problem z użyciem '__name__': Kiedy moduł zostanie zaimportowany gdzieś za pomocą importu względnego, jego wiadomości zostaną przesłane do dziennika przy użyciu krótszego' __name__'. Nie stanowi to problemu, dopóki unika się tych względnych importów, które i tak są złym stylem (jak stwierdzono w pytaniu FAQ) – c089

2

Wygląda na to, że zadziała, z tym wyjątkiem, że self nie będzie mieć atrybutu __module__; jego klasa będzie. Wezwanie rejestrator klasy poziom powinien wyglądać następująco:

self.log = logging.getLogger("%s.%s" % (self.__class__.__module__, self.__class__.__name__)) 
+1

Czy jesteś pewny, że self nie będzie mieć atrybutu __module__? Próbowałem i wydawało się, że mam. – Kiv

+0

self ma atrybut __module__. –

+0

Dziwne ... >>> z datetime data importu >>> d = date.today() >>> d .__ module__ Traceback (most recent call last): File "", wiersz 1, w AttributeError: 'datetime.date' obiekt ma atrybut '__module__' >>> d .__ class __.__ module__ 'datetime' >>> –

3

do logowania na poziomie klasy, jako alternatywa dla dekoratora pseudo-klasy można użyć metaklasa aby rejestrator na ciebie w klasie czas utworzenia ...

import logging 

class Foo(object): 
    class __metaclass__(type): 
     def __init__(cls, name, bases, attrs): 
      type.__init__(name, bases, attrs) 
      cls.log = logging.getLogger('%s.%s' % (attrs['__module__'], name)) 
    def __init__(self): 
     self.log.info('here I am, a %s!' % type(self).__name__) 

if __name__ == '__main__': 
    logging.basicConfig(level=logging.DEBUG) 
    foo = Foo() 
+0

Musiałem zmienić 'type .__ init __ (...)' na 'object .__ init __ (.. .) ', albo wystąpi błąd w pythonie 2.7:' descriptor '__init__' wymaga obiektu 'type', ale otrzymał 'str''. Ale nie mogę uruchomić tej metody w Pythonie 3.x. –

+0

Wymyśliłem to. Aby ta metoda działała również dla Pythona 3.x, muszę napisać metaklass osobno i użyć hacka, jak 'logging_metaclass_hack = logging_metaclass (" logging_metasslass ", (object,), {})' i dziedziczyć do Foo. –

Powiązane problemy