Именование протоколов Python
В Django у меня есть регистраторы повсюду, в настоящее время с жестко закодированными именами.
Для регистрации на уровне модуля (т.е. в модуле функций просмотра) у меня есть желание сделать это.
log = logging.getLogger(__name__)
Для ведения журнала на уровне классов (т.е. в методе класса __init__
) у меня есть желание сделать это.
self.log = logging.getLogger("%s.%s" % (
self.__module__, self.__class__.__name__))
Я ищу второе мнение, прежде чем заняться несколькими десятками вхождений getLogger("hard.coded.name")
.
Будет ли это работать? Кто-нибудь еще именовал своих логгеров такими же невероятными способами?
Кроме того, должен ли я сломаться и написать декоратор класса для этого определения журнала?
Ответы
Ответ 1
Обычно я не использую или не нахожу нужную информацию для регистраторов на уровне классов, но я сохраняю свои модули не более чем в нескольких классах. Простой:
import logging
LOG = logging.getLogger(__name__)
В верхней части модуля и последующих:
LOG.info('Spam and eggs are tasty!')
из любого места в файле обычно приводит меня туда, где я хочу быть. Это позволяет избежать необходимости self.log
по всему месту, что, как правило, беспокоит меня как с точки зрения "все в одном классе", и делает меня на 5 символов ближе к 79 символьным строкам, которые соответствуют.
Вы всегда можете использовать декоратор-псевдокласс:
>>> 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
Ответ 2
Для ведения журнала на уровне классов, в качестве альтернативы декоратору псевдокласса, вы можете использовать метакласс, чтобы сделать регистратор для вас во время создания класса...
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()
Ответ 3
Похоже, что это сработает, за исключением того, что self
не будет иметь атрибут __module__
; его класс будет. Вызов регистратора на уровне класса должен выглядеть так:
self.log = logging.getLogger( "%s.%s" % ( self.__class__.__module__, self.__class__.__name__ ) )