Несовместимость журналирования Python между 2.5 и 2.6 - PullRequest
6 голосов
/ 19 июня 2009

Не могли бы вы помочь мне решить следующую проблему несовместимости между Python 2.5 и 2.6?

logger.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.
$

Ответы [ 4 ]

8 голосов
/ 19 июня 2009

Это ошибка, которая была исправлена ​​между 2.5 и 2.6. Функция fileConfig () предназначена для одноразовой конфигурации и поэтому не должна вызываться более одного раза - однако вы решаете это организовать. Предполагаемое поведение fileConfig заключается в отключении любых регистраторов, которые явно не упомянуты в конфигурации, и оставлении включенными упомянутых регистраторов и их дочерних элементов; ошибка приводила к отключению детей, когда им не следовало этого делать. В примере конфигурации регистратора упоминаются регистраторы «a» и «b»; после вызова getLogger ('a.submod') создается дочерний регистратор. Второй вызов fileConfig неправильно отключает это в Python 2.5 - в Python 2.6 регистратор не отключен, так как он является потомком регистратора, явно упомянутого в конфигурации.

1 голос
/ 19 июня 2009

Я сам не понимаю причины такого поведения, но, как вы хорошо заявили в 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

0 голосов
/ 19 июня 2009

Мне удалось это исправить, изменив имена регистраторов, например, в обоих файлах:

logging.config.fileConfig('logger.conf')
a_log = logging.getLogger('a')
b_log = logging.getLogger('b')

Я не уверен в точной ошибке, но модуль логгера v2.5, похоже, испытывает проблемы при сопоставлении имен, переданных в getLogger() с именами в файле конфигурации.

0 голосов
/ 19 июня 2009

Интересно ... Я немного поиграл в консоли, и похоже, что второй вызов 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 во второй раз, мой экземпляр регистратора прекратит запись. Получение нового экземпляра журнала не помогает, так как это тот же объект. Если я подожду до тех пор, пока не настрою оба раза для извлечения экземпляров регистратора, то все будет работать - вот почему экземпляр blog работает.

Я предлагаю отложить захват экземпляров регистратора до тех пор, пока вы не включитесь в функции. Если вы переместите вызовы на logging.getLogger() на function_one и function_two, тогда все будет хорошо.

...