Почему log.debug() не регистрируется, когда для уровня установлено значение logging .ОТЛАДКА?

#python #python-3.x #logging

#python #python-3.x #ведение журнала

Вопрос:

Я ожидал, что следующий код выведет обе строки журнала

 import logging

log = logging.getLogger('hello')
log.setLevel(logging.DEBUG)
print(log.getEffectiveLevel())
log.debug('debug log')
log.critical('critical log')
  

Вывод

 10
critical log
  

Уровень правильно установлен на 10 (что соответствует DEBUG ) и, несмотря на это log.debug('debug log') , ничего не выводит — почему?

Комментарии:

1. вы имеете в виду печать журнала в stdout или stderr ?

2. @MiguelTrejo: в чем разница? сообщения отладки будут печататься в другом месте, кроме критических? И на это в другом месте не повлияет .setLevel() ?

3. Вы устанавливаете уровень только в самом регистраторе, а не в начальном обработчике, который будет использоваться для печати сообщения журнала со стандартной ошибкой. Обработчики и регистраторы имеют разные уровни, так что (например) один регистратор может записывать отладочные сообщения на консоль, но только серьезные ошибки в обработчик SMTP, чтобы уведомить кого-то о проблеме, которую необходимо решить.

Ответ №1:

Вы не настроили систему ведения журнала, поэтому она по-прежнему использует значения по умолчанию (предупреждение об уровне для корневого регистратора).

https://docs.python.org/3/library/logging.html#logging.basicConfig говорит basicConfig

Выполняет базовую конфигурацию для системы ведения журнала, создавая StreamHandler с форматером по умолчанию и добавляя его в корневой регистратор.

Настройка системы ведения журнала с basicConfig помощью first создаст обработчик и форматировщик, которые будет использовать ваш регистратор:

 logging.basicConfig()
log = logging.getLogger('hello')
log.setLevel(logging.DEBUG)
print(log.getEffectiveLevel())
log.debug('debug log')
log.critical('critical log')
  

Выводит:

 10
DEBUG:hello:debug log
CRITICAL:hello:critical log
  

В Logger.callHandlers каждый обработчик сравнивает уровень записи журнала со своим уровнем. Если обработчиков нет, он будет использовать значение по умолчанию для ПРЕДУПРЕЖДЕНИЯ.

Комментарии:

1. Спасибо — так что в моем случае мой log вывод по-прежнему зависит WARNING от уровня по умолчанию, несмотря на то, что он фактически установлен на DEBUG ?

2. Да, вы настроили свой регистратор на DEBUG, но он не подключен к обработчику (его еще нет). Попробуйте print('handlers=', logging.getLogger().handlers) с и без basicConfig . Документы по обработчику ( docs.python.org/3/library/logging.html#logging . Обработчик ) показывает, что __init__(level=NOTSET) метод принимает параметр уровня.

3. Но если обработчиков нет, как может отображаться сообщение о критическом уровне? Потому что это было обработано регистратором корневого уровня? (и, несмотря на наличие собственного регистратора, каким-то образом подключился к корневому регистратору?)

4. Если их нет, используется уровень ПРЕДУПРЕЖДЕНИЯ по умолчанию: github.com/python/cpython/blob/master/Lib/logging /…

5. @WoJ причина, по которой что-то отображается, заключается в том, что когда обработчики не настроены, используется внутренний «обработчик последней инстанции», который имеет уровень WARNING . Документировано здесь: docs.python.org/3/library /…

Ответ №2:

С помощью a StreamHandler это будет

отправляет выходные данные журнала в такие потоки, как sys.stdout, sys.stderr или любой файлоподобный объект «

согласно документации

 import logging 
import sys

# Initialize Logger and set Level to DEBUG
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# Initialize a Handler to print to stdout
handler = logging.StreamHandler(sys.stdout)

# Format Handler output
logFormatter = logging.Formatter(
    "%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p"
)
handler.setFormatter(logFormatter)

# Set Handler Level to DEBUG
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)

logger.debug('Debug Info')
>>> 09/19/2020 09:01:00 PM Debug Info
  

Ответ №3:

Вам нужно добавить обработчик потока

 import logging

log = logging.getLogger('hello')
log.setLevel(logging.DEBUG)

# # Create a file handler to store the logs
file_handler = logging.FileHandler('test.log')
log.addHandler(file_handler)

# # Send output to terminal
stream_handler = logging.StreamHandler()
log.addHandler(stream_handler)

log.debug('debug log')