Как комментарии @offbyone, можно добавить избыточные обработчики к одному и тому же экземпляру регистратора.
Документы python для регистрации say-
"Несколько вызовов getLogger () с одинаковым именем вернут
ссылка на тот же объект регистратора. "
Так что нам не нужно беспокоиться о том, чтобы сделать реализацию единой, как это уже есть.
К сожалению, то же самое не соответствует действительности для обработчиков, связанных с одним и тем же экземпляром регистратора. Там может быть прикрепленным дубликатом обработчиков.
1017 * ПРИМЕР- *
Скопируйте этот код и сохраните его в main.py
import logging
print 'inside main.py',
print '-'*50
def logger():
print 'initializing logger....'
logPath = '.'
fileName = 'temp'
# configure log formatter
logFormatter = logging.Formatter("%(asctime)s [%(filename)s] [%(funcName)s] [%(levelname)s] [%(lineno)d] %(message)s")
# configure file handler
fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
# configure stream handler
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
# get the logger instance
logger = logging.getLogger(__name__)
# set the logging level
logger.setLevel(logging.DEBUG)
print 'adding handlers- '
#if not len(logger.handlers):
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
print 'logger initialized....\n'
print 'associated handlers - ', len(logger.handlers)
for handler in logger.handlers:
print handler
print
return logger
main_logger = logger()
main_logger.info('utilizing main.py logger.')
print 'exiting main.py',
print '-'*50
и следующий код в sub.py
print 'inside sub.py',
print '-'*50
print 'importing main.py'
import main
print 'imported main.py'
import logging
print 'getting logger instance in sub'
sub_logger = main.logger()
print 'got logger instance in sub'
sub_logger.info("utilizing sub_logger")
print 'exiting sub.py',
print '-'*50
Выполнить sub.py
narayan@y510p:~/code/so$ python sub.py
inside sub.py --------------------------------------------------
importing main.py
inside main.py --------------------------------------------------
initializing logger....
adding handlers-
logger initialized....
associated handlers - 2
<logging.FileHandler object at 0x7f7158740c90>
<logging.StreamHandler object at 0x7f7158710b10>
2015-08-04 07:41:01,824 [main.py] [<module>] [INFO] [41] utilizing main.py logger.
exiting main.py --------------------------------------------------
imported main.py
getting logger instance in sub
initializing logger....
adding handlers-
logger initialized....
associated handlers - 4 # <===== 4 handlers (duplicates added)
<logging.FileHandler object at 0x7f7158740c90>
<logging.StreamHandler object at 0x7f7158710b10>
<logging.FileHandler object at 0x7f7158710bd0>
<logging.StreamHandler object at 0x7f7158710c10>
got logger instance in sub
2015-08-04 07:41:01,824 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
2015-08-04 07:41:01,824 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
exiting sub.py --------------------------------------------------
Следовательно, множественные вызовы метода, возвращающего один и тот же регистратор, добавили дублирующиеся обработчики.
Теперь, на ваш вопрос-
есть ли способ проверить, существует ли обработчик
Да, есть -
logger.handlers
возвращает список всех обработчиков, связанных с данным logger
.
Перед добавлением обработчиков в экземпляр регистратора, убедитесь, что не добавляете дублирующиеся обработчики
В main.py просто снимите комментарий со строки, которая говорит if not len(logger.handlers):
, и сделайте отступ в следующих двух строках правильно -
if not len(logger.handlers):
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
Теперь снова запустите sub.py
narayan@y510p:~/code/so$ python sub.py
inside sub.py --------------------------------------------------
importing main.py
inside main.py --------------------------------------------------
initializing logger....
adding handlers-
logger initialized....
associated handlers - 2
<logging.FileHandler object at 0x7fd67a891c90>
<logging.StreamHandler object at 0x7fd67a862b10>
2015-08-04 08:14:45,620 [main.py] [<module>] [INFO] [41] utilizing main.py logger.
exiting main.py --------------------------------------------------
imported main.py
getting logger instance in sub
initializing logger....
adding handlers-
logger initialized....
associated handlers - 2 # <===== Still 2 handlers (no duplicates)
<logging.FileHandler object at 0x7fd67a891c90>
<logging.StreamHandler object at 0x7fd67a862b10>
got logger instance in sub
2015-08-04 08:14:45,620 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
exiting sub.py --------------------------------------------------
Далее, если вы хотите ограничить тип обработчиков, которые будут добавлены к экземпляру регистратора, вы можете сделать что-то вроде этого -
print 'adding handlers- '
# allows to add only one instance of file handler and stream handler
if len(logger.handlers) > 0:
print 'making sure we do not add duplicate handlers'
for handler in logger.handlers:
# add the handlers to the logger
# makes sure no duplicate handlers are added
if not isinstance(handler, logging.FileHandler) and not isinstance(handler, logging.StreamHandler):
logger.addHandler(fileHandler)
print 'added file handler'
logger.addHandler(consoleHandler)
print 'added stream handler'
else:
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
print 'added handlers for the first time'
Надеюсь, это поможет!
Edit:
К сожалению, то же самое не соответствует действительности для связанных обработчиков
с тем же экземпляром регистратора. Там может быть дубликатом
обработчики прилагаются.
Оказывается, что вышеприведенное утверждение не совсем верно.
Предположим, мы создали и настроили регистратор с именем 'main_logger' в главном модуле (который просто настраивает регистратор, ничего не возвращает).
# get the logger instance
logger = logging.getLogger("main_logger")
# configuration follows
...
Теперь в подмодуле, если мы создадим дочерний регистратор, следуя иерархии имен 'main_logger.sub_module_logger' , нам не нужно настраивать его в подмодуле. Достаточно просто создать регистратор, следуя иерархии имен.
# get the logger instance
logger = logging.getLogger("main_logger.sub_module_logger")
# no configuration needed
# it inherits the configuration from the parent logger
...
И это не добавит дубликат обработчика.
Reference- Использование регистрации в нескольких модулях