Logging setLevel, как это работает
В протоколировании документации есть следующий пример:
import logging
# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
Почему я должен установить уровень logging.DEBUG
дважды, для Logger
и для StreamHandler
?
Я понимаю, что ch.setLevel(logging.DEBUG)
установит уровень отладки для обработчика потока. Но каков эффект установки уровня на регистратор? Где этот уровень отражается?
Я получаю тот же вывод консоли, если я изменю уровень, например, INFO
либо на Logger
, либо на StreamHandler
.
То есть:
...........
logger.setLevel(logging.INFO)
............
ch.setLevel(logging.DEBUG)
дает тот же вывод в консоли, что
...........
logger.setLevel(logging.DEBUG)
............
ch.setLevel(logging.INFO)
Ответы
Ответ 1
Здесь для тонкой настройки (у вас может быть несколько обработчиков, и каждый из них может иметь разные уровни) - вы можете безопасно не устанавливать уровень на обработчике, что приведет к его обработке всех сообщений (ака NOTSET-уровня) и отпустите уровень фильтрации в регистратор.
Logger также первыми фильтрует сообщение на основе уровня - если вы установите регистратор на INFO и все обработчики на DEBUG, вы все равно не будете получать сообщения DEBUG на обработчиках - они будут отклонены регистратором сам. Если вы установили logger в DEBUG, но все обработчики INFO, вы также не получите никаких сообщений DEBUG - потому что, пока журнал говорит "ok, обработайте это", обработчики отклоняют его (DEBUG < INFO).
Ответ 2
Почему я должен установить уровень для logging.DEBUG дважды, для регистратора и для ручного манипулятора. Я понимаю, что ch.setLevel(logging.DEBUG) установит уровень отладки для обработчика потока. Но каков эффект установки уровня на регистратор?. Где этот уровень отражен?
Это указано в документации:
"Метод setLevel(), как и в объектах журнала, определяет самую низкую степень серьезности, которая будет отправлена в соответствующий пункт назначения. Почему существуют два метода setLevel()? Уровень, установленный в журнале, определяет, какая степень сообщений, которые он передаст своим обработчикам. Уровень, установленный в каждом обработчике, определяет, какие сообщения отправляет обработчик.
Проверить под обработчиками: http://docs.python.org/2.7/howto/logging.html#logging-advanced-tutorial
Ответ 3
Думаю, полезно рассмотреть эти основные три момента, чтобы понять, как работает журнал:
-
Вы можете создать иерархию объектов Logger. Каждый из них
изначально не имеют уровня (уровень NOTSET). Эффективный уровень
Объект Logger - это первый уровень, который был установлен в иерархии
по пути до корневого регистратора (возможно, NOTSET, если ни один уровень не был
установлен).
-
Эффективный уровень регистратора используется только для определения того, следует ли запускать действие с сообщением, напрямую переданным этому регистратору.
-
Это действие - это, во-первых, передача сообщения этим обработчикам Logger,
и второй (в зависимости от значения флага распространения), передавая его каждому из обработчиков цепи предков вверху, не принимая во внимание фактические уровни каждого из регистраторов в цепочке.
Чтобы ответить на ваш вопрос, вам не нужно устанавливать его дважды в этом примере. Установка его в DEBUG только в Logger будет достаточным для включения сообщений журнала, отправленных непосредственно в ваш экземпляр Logger, чтобы попасть в консоль (поскольку уровень по умолчанию в новом StreamHandler по умолчанию является NOTSET, поэтому он все пропускает).