Несовместимость ведения журнала Python между 2.5 и 2.6
-
06-07-2019 - |
Вопрос
Не могли бы вы помочь мне решить следующую проблему несовместимости между Python 2.5 и 2.6?
logger.conf регистратор.conf:
[loggers]
keys=root,aLogger,bLogger
[handlers]
keys=consoleHandler
[formatters]
keys=
[logger_root]
level=NOTSET
handlers=consoleHandler
[logger_aLogger]
level=DEBUG
handlers=consoleHandler
propagate=0
qualname=a
[logger_bLogger]
level=INFO
handlers=consoleHandler
propagate=0
qualname=b
[handler_consoleHandler]
class=StreamHandler
args=(sys.stderr,)
module_one.py:
import logging
import logging.config
logging.config.fileConfig('logger.conf')
a_log = logging.getLogger('a.submod')
b_log = logging.getLogger('b.submod')
def function_one():
b_log.info("function_one() called.")
module_two.py:
import logging
import logging.config
logging.config.fileConfig('logger.conf')
a_log = logging.getLogger('a.submod')
b_log = logging.getLogger('b.submod')
def function_two():
a_log.info("function_two() called.")
logger.py:
from module_one import function_one
from module_two import function_two
function_one()
function_two()
Результат вызова logger.py в Ubuntu 9.04:
$ python2.5 logger.py
$
$ python2.6 logger.py
function_one() called.
function_two() called.
$
Решение
Это ошибка, которая была исправлена между 2.5 и 2.6.Функция fileConfig() предназначена для одноразовой настройки и поэтому не должна вызываться более одного раза - как бы вы ни решили это организовать.Предполагаемое поведение fileConfig заключается в отключении любых регистраторов, которые явно не упомянуты в конфигурации, и оставлении включенными упомянутых регистраторов и их дочерних элементов;ошибка приводила к отключению дочерних элементов, когда этого не должно было быть.В примере конфигурации регистратора упоминаются регистраторы 'a' и 'b';после вызова getLogger('a.submod') создается дочерний регистратор.Второй вызов fileConfig ошибочно отключает это в Python 2.5 - в Python 2.6 регистратор не отключен, поскольку он является дочерним по отношению к регистратору, явно упомянутому в конфигурации.
Другие советы
Я сам не понимаю причин такого поведения, но, как вы хорошо указали в 2.6, это работает по-другому.Мы можем предположить, что это ошибка, влияющая на 2.5
В качестве обходного пути я предлагаю следующее:
extra_module.py:
import logging
import logging.config
logging.config.fileConfig('logger.conf')
a_log = logging.getLogger('a.submod')
b_log = logging.getLogger('b.submod')
module_one.py:
from extra_module import a_log
def function_one():
a_log.info("function_one() called.")
module_two.py:
from extra_module import b_log
def function_two():
b_log.info("function_two() called.")
используя эту схему, я смог запустить logger.py на python2.5.4 с тем же поведением, что и в версии 2.6
Интересно...Я немного поиграл в консоли, и это похоже на второй вызов logging.config.fileConfig
это все портит.Хотя не уверен, почему это так...Вот расшифровка, которая показывает проблему:
lorien$ python2.5
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging
>>> import logging.config
>>> logging.config.fileConfig('logger.conf')
>>> alog = logging.getLogger('a.submod')
>>> alog.info('foo')
foo
>>> import logging
>>> import logging.config
>>> alog.info('foo')
foo
>>> logging.config.fileConfig('logger.conf')
>>> alog.info('foo')
>>> alog = logging.getLogger('a.submod')
>>> alog.info('foo')
>>>
>>> blog = logging.getLogger('b.submod')
>>> blog.info('foo')
foo
>>>
Как только я позвоню logging.config.fileConfig
во второй раз мой экземпляр logger прекращает ведение журнала.Захват нового экземпляра журнала не помогает, поскольку это один и тот же объект.Если я подожду, пока после настройки оба раза не будут извлечены экземпляры регистратора, тогда все заработает - вот почему blog
экземпляр работает.
Мое предложение состоит в том, чтобы отложить захват экземпляров logger до тех пор, пока вы не перейдете к функциям.Если вы переместите вызовы в logging.getLogger()
в function_one
и function_two
, тогда все работает хорошо.
Я смог исправить это, изменив имена регистраторов следующим образом в обоих файлах:
logging.config.fileConfig('logger.conf')
a_log = logging.getLogger('a')
b_log = logging.getLogger('b')
Я не уверен в точной ошибке, но модуль регистратора версии v2.5, похоже, испытывает проблемы с сопоставлением имен, переданных getLogger()
с именами в конфигурационном файле.