Python – Избегать прохождения ссылки на регистратор между функциями?

У меня есть простой скрипт Python, который использует встроенный logging .

Я настраиваю ведение журнала внутри функции. Основная структура будет примерно такой:

 #!/usr/bin/env python import logging import ... def configure_logging(): logger = logging.getLogger("my logger") logger.setLevel(logging.DEBUG) # 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) logger.addHandler(ch) # Setup file logging as well fh = logging.FileHandler(LOG_FILENAME) fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) logger.addHandler(fh) return logger def count_parrots(): ... logger.debug?? if __name__ == '__main__': logger = configure_logging() logger.debug("I'm a log file") parrots = count_parrots() 

Я могу вызвать логгер изнутри __main__ . Однако как я могу вызвать регистратор из функции count_parrots ()? Какой самый pythonic способ обработки конфигурации регистратора, как это?

5 Solutions collect form web for “Python – Избегать прохождения ссылки на регистратор между функциями?”

Вы можете либо использовать корневой (по умолчанию) регистратор, и, таким образом, уровень модуля функции logging.debug , … или получить ваш регистратор в функции, используя его. Действительно, функция getLogger – это фабрично-подобная функция с реестром (однопользовательская), т. getLogger Она всегда возвращает тот же экземпляр для данного имени журнала. Таким образом, вы можете получить свой регистратор в count_parrots, просто используя

 logger = logging.getLogger("my logger") 

в начале. Тем не менее, соглашение заключается в использовании точечного иерархического имени для вашего регистратора. См. http://docs.python.org/library/logging.html#logging.getLogger

РЕДАКТИРОВАТЬ:

Вы можете использовать декоратор, чтобы добавить поведение журнала в свои индивидуальные функции, например:

 def debug(loggername): logger = logging.getLogger(loggername) def log_(enter_message, exit_message=None): def wrapper(f): def wrapped(*args, **kargs): logger.debug(enter_message) r = f(*args, **kargs) if exit_message: logger.debug(exit_message) return r return wrapped return wrapper return log_ my_debug = debug('my.logger') @my_debug('enter foo', 'exit foo') def foo(a, b): return a+b 

вы можете «жестко закодировать» имя регистратора и удалить закрытие верхнего уровня и my_debug.

Вы можете просто сделать:

 logger = logging.getLogger("my logger") 

в вашем count_parrots() . Когда вы передаете имя, которое использовалось ранее (то есть «мой регистратор»), модуль регистрации вернет тот же экземпляр, который был создан в соответствии с этим именем.

Обновление: из учебника по протоколированию (см.

getLogger () возвращает ссылку на экземпляр журнала с указанным именем, если он указан, или root, если нет. Имена представляют собой иерархические структуры, разделенные периодом. Несколько вызовов в getLogger () с тем же именем возвращают ссылку на тот же объект журнала.

Типичным способом обработки журнала является наличие логатора на каждом модуле, хранящегося в глобальной переменной. Любые функции и методы внутри этого модуля затем ссылаются только на тот же экземпляр регистратора.

Это кратко обсуждается во вступлении к учебному руководству по продвижению в документации: http://docs.python.org/howto/logging.html#advanced-logging-tutorial

Вы можете передавать экземпляры журнала в качестве параметров, но это обычно бывает редко.

Я запутался в том, как глобальные переменные работают в Python. Внутри функции вам нужно только объявить global logger если вы делаете что-то вроде logger = logging.getLogger("my logger") и надеетесь изменить глобальный logger .

Поэтому, чтобы изменить ваш пример, вы можете создать глобальный объект журнала в начале файла. Если ваш модуль может быть импортирован другим, вы должны добавить NullHandler чтобы, если импортер библиотеки не хочет, чтобы регистрация была включена, у них нет проблем с вашей lib ( ref ).

 #!/usr/bin/env python import logging import ... logger = logging.getLogger("my logger").addHandler(logging.NullHandler()) def configure_logging(): logger.setLevel(logging.DEBUG) # 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) logger.addHandler(ch) # Setup file logging as well fh = logging.FileHandler(LOG_FILENAME) fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) logger.addHandler(fh) def count_parrots(): ... logger.debug('counting parrots') ... return parrots if __name__ == '__main__': configure_logging() logger.debug("I'm a log file") parrots = count_parrots() 

Вы можете предоставить logger качестве аргумента для count_parrots() Или, что бы я сделал, создайте попугаев классов и используем logger как один из его методов.

Python - лучший язык программирования в мире.