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 чтобы запутаться.

вопрос

  1. почему сообщение регистрируется из d при вызове с уровня модуля, но не изнутри d.foo()?
  2. и как я могу достичь цели ведения журнала из нескольких модулей, настраивая только ведение журнала в основной программе?

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()