Python logging несколько модулей logger не работает вне основной программы
моя цель-войти из нескольких модулей, при этом только настройка регистратора в одном месте-в основной программе. Как показано в ответ, следует включить
logging.config.fileConfig('/path/to/logging.conf')
в основной программе, затем во все остальные модули включить
logger = logging.getLogger(__name__)
я считаю, что это то, что я сделал ниже, но я получаю неожиданные поведение.
Си.ру
# c.py
import logging
import logging.config
import d
logging.config.fileConfig("logging.conf")
logger = logging.getLogger(__name__)
logger.warning('logging from c')
d.foo()
д'.ру
# d.py
import logging
logger = logging.getLogger(__name__)
# this will print when d is imported
logger.warning('logging from d on import')
def foo():
# this does not print
logger.warning("logging from d on call foo()")
выход
$ python c.py
logging from d on import
logging from c
что бы я ни делал, это когда d.foo()
выполняет c.py
, что сообщение будет получено с d
, однако, это не так. Это сбивает с толку, потому что когда регистратор вызывается с уровня модуля в d
, он регистрирует сообщение на консоль, но при вызове изнутри foo()
это не так.
конфиг файл
[loggers]
keys=root
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(message)s
datefmt=
дальнейший анализ
поэтому я заметил, что если я удалю строку
logging.config.fileConfig("logging.conf")
С c.py
, затем вход из d.foo()
работает, как ожидалось. Так что либо что-то не так в файле конфигурации, либо из-за того, что я обеспечить файл конфигурации что-то вызывает регистратор в d.py
чтобы запутаться.
вопрос
- почему сообщение регистрируется из
d
при вызове с уровня модуля, но не изнутриd.foo()
? - и как я могу достичь цели ведения журнала из нескольких модулей, настраивая только ведение журнала в основной программе?
2 ответов
проблема заключается в том, что
import d
перед
logging.config.fileConfig("logging.conf")
как указал @davidejones. Вот!--20-->почему:
как говорится в docs, когда logging.config.fileConfig()
называется, его поведение по умолчанию -отключить все существующие регистраторы. Так когда import d
происходит logger
инициализируется в d
, когда logging.config.fileConfig()
называется logger
на d
отключен, поэтому мы не видели любое ведение журнала, когда d.foo()
называлась.
решение
logging.config.fileConfig()
принимает аргумент, disable_existing_loggers
, которая составляет True
по умолчанию. Использовать
logging.config.fileConfig("logging.conf", disable_existing_loggers=False)
и выход становится
>>> python c.py
logging from d on import
logging from c
logging from d on call foo()
как и ожидалось.
Я думаю, что импорт d происходит до конфигурации регистратора, поэтому делать что-то вроде этого может дать то, что вы хотите?
# c.py
import logging
import logging.config
logging.config.fileConfig("logging.conf")
logger = logging.getLogger(__name__)
import d
logger.warning('logging from c')
d.foo()
это дает мне такие результаты
logging from d on import
logging from c
logging from d on call foo()
редактировать
глядя на код, возможно, имеет смысл иметь отдельный файл, чтобы иметь настройку ведения журнала, то вы импортируете, что один раз в главном файле другие модули будут иметь его, и это не выглядит так грязно. Так что, возможно, имея logsetup.py
как это
import logging
import logging.config
logging.config.fileConfig("logging.conf")
и затем c.py выглядит так, вместо этого, который по-прежнему дает те же результаты
# c.py
import logsetup
import logging
import d
logger = logging.getLogger(__name__)
logger.warning('logging from c')
d.foo()