Spec-Zone.ru › Python 3.8

logging.config — Настройка ведения журнала

Исходный код: Lib/logging/config.py

Важно

Эта страница содержит только справочную информацию. Для обучающих материалов обратитесь к

  • Базовый учебник
  • Расширенный учебник
  • Пособие по ведению журнала

В этом разделе описан API для настройки модуля ведения журнала.

Функции конфигурации

Следующие функции настраивают модуль ведения журнала. Они находятся в модуле logging.config. Их использование необязательно — вы можете настроить модуль ведения журнала, используя эти функции или вызывая основной API (определённый в logging) и определяя обработчики, объявленные в logging или logging.handlers.

logging.config.dictConfig(config)

Получает конфигурацию ведения журнала из словаря. Содержимое этого словаря описано в Схеме словаря конфигурации ниже.

Если при конфигурации возникнет ошибка, эта функция вызовет ValueError, TypeError, AttributeError или ImportError с соответствующим сообщением об ошибке. Ниже приведён (возможно, неполный) список условий, которые приведут к ошибке:

  • Значение level, которое не является строкой или является строкой, не соответствующей фактическому уровню ведения журнала.
  • Значение propagate которое не является логическим значением.
  • Идентификатор, для которого нет соответствующего назначения.
  • Несуществующий идентификатор обработчика, обнаруженный во время инкрементного вызова.
  • Неправильное имя логгера.
  • Невозможность разрешения к внутренней или внешней объекту.

Разбор выполняется классом DictConfigurator, конструктору которого передаётся словарь, используемый для конфигурации, и у которого есть метод configure(). Модуль logging.config имеет вызываемый атрибут dictConfigClass, который изначально устанавливается в значение DictConfigurator. Вы можете заменить значение dictConfigClass на подходящую реализацию от себя.

dictConfig() вызывает dictConfigClass, передавая указанный словарь, а затем вызывает метод configure() на возвращённом объекте, чтобы применить конфигурацию:

def dictConfig(config):
    dictConfigClass(config).configure()

Например, подкласс DictConfigurator может вызвать DictConfigurator.__init__() в собственном методе __init__(), затем настроить пользовательские префиксы, которые можно будет использовать в последующем вызове configure().

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

Введено в версии 3.2.

logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)

Читает конфигурацию ведения журнала из файла в формате configparser. Формат файла должен быть таким, как описано в Формат файла конфигурации. Эту функцию можно вызывать несколько раз из приложения, что позволит конечному пользователю выбирать из различных предварительно подготовленных конфигураций (если разработчик предоставит механизм для отображения выбора и загрузки выбранной конфигурации).

Параметры
  • fname – Имя файла или файл-подобный объект или экземпляр, полученный из RawConfigParser. Если передан экземпляр, полученный из RawConfigParser, он используется как есть. В противном случае создаётся экземпляр Configparser, и конфигурация читается им из объекта, переданного в fname. Если у объекта есть метод readline(), он предполагается файлоподобным объектом и читается с помощью read_file(); в противном случае предполагается имя файла и передаётся в read().
  • defaults – Значения по умолчанию, которые будут переданы в ConfigParser, могут быть указаны в этом аргументе.
  • disable_existing_loggers – Если указано как False, логгеры, которые существуют при выполнении этого вызова, остаются включёнными. Значение по умолчанию True сохраняет старое поведение для обратной совместимости. Это поведение заключается в отключении всех существующих логгеров, кроме корневого, если они или их предки явно не указаны в конфигурации ведения журнала.

Изменено в версии 3.4: Экземпляр подкласса RawConfigParser теперь принимается в качестве значения для fname. Это способствует:

  • Использованию файла конфигурации, где конфигурация ведения журнала является лишь частью общей конфигурации приложения.
  • Использованию конфигурации, считанной из файла и затем изменённой приложением (например, на основе параметров командной строки или других аспектов среды выполнения) перед передачей в fileConfig.
logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)

Запускает сервер сокета на указанном порту и слушает новые конфигурации. Если порт не указан, используется значение по умолчанию модуля DEFAULT_LOGGING_CONFIG_PORT. Конфигурации ведения журнала будут отправляться как файл, подходящий для обработки с помощью dictConfig() или fileConfig(). Возвращает экземпляр Thread, на котором вы можете вызвать start() для запуска сервера и который вы можете join() при необходимости. Чтобы остановить сервер, вызовите stopListening().

Аргумент verify, если указан, должен быть вызываемым объектом, который должен проверять, являются ли полученные через сокет байты допустимыми и должны ли они обрабатываться. Это можно сделать, зашифровав и/или подписав то, что отправляется через сокет, таким образом, что вызываемый объект verify может выполнить проверку подписи и/или расшифровку. Вызываемый объект verify вызывается с одним аргументом — полученными через сокет байтами — и должен вернуть обрабатываемые байты или None, чтобы указать, что байты следует отбросить. Возвращаемые байты могут быть такими же, как переданные байты (например, если выполняется только проверка), или они могут быть совершенно другими (если выполняется расшифровка).

Чтобы отправить конфигурацию в сокет, прочтите файл конфигурации и отправьте его в сокет в виде последовательности байтов, предваряемых четырёхбайтовой строкой длины, упакованной в двоичный вид с помощью struct.pack('>L', n).

Примечание

Поскольку части конфигурации передаются через eval(), использование этой функции может создать угрозу безопасности для пользователей. Хотя функция связывается только с сокетом на localhost, и поэтому не принимает подключения от удалённых машин, существуют сценарии, в которых недоверенный код может выполняться от имени процесса, вызывающего listen(). В частности, если процесс, вызывающий listen(), выполняется на многопользовательской машине, где пользователи не могут доверять друг другу, злонамеренный пользователь может организовать выполнение практически произвольного кода в процессе жертвы, просто подключившись к сокету listen() жертвы и отправив конфигурацию, которая выполняет любой код, который злоумышленник хочет выполнить в процессе жертвы. Это особенно легко сделать, если используется порт по умолчанию, но несложно даже если используется другой порт).

Чтобы избежать риска этого, используйте аргумент verify к listen(), чтобы предотвратить применение неизвестных конфигураций.

Изменено в версии 3.4: Добавлен аргумент verify.

Примечание

Если вы хотите отправить конфигурации в слушатель, которые не отключают существующие логгеры, вам необходимо использовать формат JSON для конфигурации, который будет использовать dictConfig() для конфигурации. Этот метод позволяет вам указать disable_existing_loggers как False в отправляемой вами конфигурации.

END_OF_DOCUMENT_MARKER
logging.config.stopListening()

Останавливает сервер прослушивания, который был создан с помощью вызова listen(). Обычно это делается перед вызовом join() для значения, возвращаемого из listen().

Схема словаря конфигурации

Описание конфигурации логгирования требует перечисления различных объектов для создания и связей между ними; например, вы можете создать обработчик с именем «console» и указать, что логгер с именем «startup» будет отправлять свои сообщения в обработчик «console». Эти объекты не ограничиваются теми, которые предоставляются модулем logging, поскольку вы можете написать собственный класс форматирования или обработчика. Параметры этих классов также могут потребовать включения внешних объектов, таких как sys.stderr. Синтаксис описания этих объектов и соединений определен в Соединения объектов ниже.

Подробности схемы словаря

Словарь, передаваемый в dictConfig(), должен содержать следующие ключи:

  • version - значение должно быть целым числом, представляющим версию схемы. В настоящее время единственным допустимым значением является 1, но наличие этого ключа позволяет схеме эволюционировать, сохраняя при этом обратную совместимость.

Все остальные ключи необязательны, но если они присутствуют, они будут интерпретироваться, как описано ниже. Во всех случаях ниже, где упоминается «словарь конфигурации», он проверяется на наличие специального ключа '()', чтобы определить, требуется ли пользовательская инициализация. В противном случае используется контекст для определения того, что следует инициализировать.

  • formatters - соответствующее значение будет словарем, в котором каждый ключ — это идентификатор форматирования, а каждое значение — это словарь, описывающий, как настроить соответствующий экземпляр Formatter.

    В словаре конфигурации ищутся ключи format и datefmt (с значениями по умолчанию None) и они используются для построения экземпляра Formatter.

    Изменено в версии 3.8: в раздел formatters словаря конфигурации может быть добавлен ключ validate (по умолчанию True) для проверки формата.

  • filters - соответствующее значение будет словарем, в котором каждый ключ — это идентификатор фильтра, а каждое значение — это словарь, описывающий, как настроить соответствующий экземпляр Filter.

    В словаре конфигурации ищется ключ name (по умолчанию пустая строка), и он используется для построения экземпляра logging.Filter.

  • handlers - соответствующее значение будет словарем, в котором каждый ключ — это идентификатор обработчика, а каждое значение — это словарь, описывающий, как настроить соответствующий экземпляр Handler.

    В словаре конфигурации ищутся следующие ключи:

    • class (обязательно). Полное квалифицированное имя класса обработчика.
    • level (необязательно). Уровень обработчика.
    • formatter (необязательно). Идентификатор форматирования для этого обработчика.
    • filters (необязательно). Список идентификаторов фильтров для этого обработчика.

    Все другие ключи передаются как ключевые аргументы в конструктор обработчика. Например, если есть фрагмент:

    handlers:
      console:
        class : logging.StreamHandler
        formatter: brief
        level   : INFO
        filters: [allow_foo]
        stream  : ext://sys.stdout
      file:
        class : logging.handlers.RotatingFileHandler
        formatter: precise
        filename: logconfig.log
        maxBytes: 1024
        backupCount: 3
    

    обработчик с идентификатором console инициализируется как logging.StreamHandler, используя sys.stdout в качестве базового потока. Обработчик с идентификатором file инициализируется как logging.handlers.RotatingFileHandler с ключевыми аргументами filename='logconfig.log', maxBytes=1024, backupCount=3.

  • loggers - соответствующее значение будет словарем, в котором каждый ключ — это имя логгера, а каждое значение — это словарь, описывающий, как настроить соответствующий экземпляр Logger.

    В словаре конфигурации ищутся следующие ключи:

    • level (необязательно). Уровень логгера.
    • propagate (необязательно). Параметр распространения логгера.
    • filters (необязательно). Список идентификаторов фильтров для этого логгера.
    • handlers (необязательно). Список идентификаторов обработчиков для этого логгера.

    Указанные логгеры будут настроены в соответствии с уровнем, параметром распространения, фильтрами и обработчиками.

  • root - это конфигурация для корневого логгера. Обработка конфигурации будет такой же, как для любого логгера, за исключением того, что параметр propagate не применим.
  • incremental - определяет, интерпретируется ли конфигурация как инкрементная по отношению к существующей конфигурации. По умолчанию это False, что означает, что указанная конфигурация заменяет существующую конфигурацию с теми же семантиками, что и используемый API fileConfig().

    Если указанное значение равно True, конфигурация обрабатывается, как описано в разделе Инкрементальная конфигурация.

  • disable_existing_loggers - определяет, должны ли быть отключены любые существующие логгеры, отличные от корневого. Этот параметр аналогичен параметру с таким же именем в fileConfig(). Если отсутствует, этот параметр имеет значение по умолчанию True. Это значение игнорируется, если incremental равно True.

Инкрементальная конфигурация

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

Кроме того, нет веских оснований для произвольного изменения графа объектов логгеров, обработчиков, фильтров, форматировщиков во время выполнения после настройки конфигурации; подробность логгеров и обработчиков можно контролировать только путем установки уровней (и, в случае с логгерами, флагов распространения).

Произвольное изменение графа объектов безопасным способом в многопоточной среде представляет собой проблему; хотя это не невозможно, преимущества не стоят сложности, которую это добавляет в реализацию.

Таким образом, когда ключ incremental в словаре конфигурации присутствует и равен True, система полностью проигнорирует любые записи formatters и filters, и обработает только настройки level в записях handlers, а также настройки level и propagate в записях loggers и root.

Использование значения в словаре конфигурации позволяет передавать конфигурации через сеть в виде закодированных словарей в сокет-листенер. Таким образом, уровень логгирования долгоживущего приложения можно изменять со временем без необходимости остановки и перезапуска приложения.

Соединения объектов

Схема описывает набор объектов логгирования — логгеры, обработчики, форматировщики, фильтры — которые соединены друг с другом в графе объектов. Таким образом, схема должна представлять соединения между объектами. Например, предположим, что после настройки к определенному логгеру прикреплен определенный обработчик. В целях данного обсуждения мы можем сказать, что логгер представляет источник, а обработчик — пункт назначения соединения между ними. Конечно, в настроенных объектах это представлено тем, что логгер содержит ссылку на обработчик. В словаре конфигурации это делается путем присвоения каждому объекту-получателю уникального идентификатора и затем использования этого идентификатора в конфигурации объекта-источника для указания наличия соединения между объектом-источником и объектом-получателем с этим идентификатором.

Например, рассмотрим следующий фрагмент YAML:

formatters:
  brief:
    # configuration for formatter with id 'brief' goes here
  precise:
    # configuration for formatter with id 'precise' goes here
handlers:
  h1: #This is an id
   # configuration of handler with id 'h1' goes here
   formatter: brief
  h2: #This is another id
   # configuration of handler with id 'h2' goes here
   formatter: precise
loggers:
  foo.bar.baz:
    # other configuration for logger 'foo.bar.baz'
    handlers: [h1, h2]

(Примечание: здесь используется YAML, так как он немного понятнее, чем эквивалентная форма словаря Python.)

Идентификаторы логгеров — это имена логгеров, которые используются в программировании для получения ссылки на эти логгеры, например foo.bar.baz. Идентификаторы форматировщиков и фильтров могут быть любыми строковыми значениями (например, brief, precise выше), и они являются временными, так как имеют смысл только для обработки словаря конфигурации и используются для определения соединений между объектами, а не сохраняются нигде при завершении вызова конфигурации.

В приведенном фрагменте указано, что логгер с именем foo.bar.baz должен иметь два прикрепленных обработчика, описанных идентификаторами обработчиков h1 и h2. Форматировщик для h1 — это тот, который описан идентификатором brief, а форматировщик для h2 — тот, который описан идентификатором precise.

Пользовательские объекты

Схема поддерживает пользовательские объекты для обработчиков, фильтров и форматеров. (Логгеры не нуждаются в разных типах для разных экземпляров, поэтому в этой схеме конфигурации нет поддержки пользовательских классов логгеров.)

Объекты, подлежащие конфигурации, описываются словарями, которые детализируют их конфигурацию. В некоторых местах система логирования сможет определить, как создать объект из контекста, но когда необходимо создать пользовательский объект, система не будет знать, как это сделать. Чтобы обеспечить полную гибкость для создания пользовательских объектов, пользователю необходимо предоставить «фабрику» — вызываемый объект, который вызывается со словарем конфигурации и возвращает созданный объект. Это обозначается абсолютным импортируемым путем к фабрике, доступным по специальному ключу '()'. Вот конкретный пример:

formatters:
  brief:
    format: '%(message)s'
  default:
    format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
    datefmt: '%Y-%m-%d %H:%M:%S'
  custom:
      (): my.package.customFormatterFactory
      bar: baz
      spam: 99.9
      answer: 42

Вышеприведённый фрагмент YAML определяет три форматера. Первый, с идентификатором brief, является стандартным экземпляром logging.Formatter со строкой формата, указанной в спецификации. Второй, с идентификатором default, имеет более длинный формат и также явно определяет формат времени, и приведет к созданию logging.Formatter с этими двумя строками формата. Представленные в виде исходного кода Python, форматеры brief и default имеют подсловари конфигурации:

{
  'format' : '%(message)s'
}

и:

{
  'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
  'datefmt' : '%Y-%m-%d %H:%M:%S'
}

соответственно, и поскольку эти словари не содержат специального ключа '()', создание экземпляра определяется из контекста: в результате создаются стандартные экземпляры logging.Formatter. Подсловарь конфигурации для третьего форматера, с идентификатором custom, имеет вид:

{
  '()' : 'my.package.customFormatterFactory',
  'bar' : 'baz',
  'spam' : 99.9,
  'answer' : 42
}

и содержит специальный ключ '()', что означает необходимость создания пользовательского экземпляра. В этом случае будет использоваться указанная функция-фабрика. Если это фактическая вызываемая функция, она будет использоваться напрямую; в противном случае, если вы укажете строку (как в примере), фактическая вызываемая функция будет найдена с помощью стандартных механизмов импорта. Функция будет вызвана с оставшимися элементами в подсловаре конфигурации в качестве ключевых аргументов. В приведенном выше примере предполагается, что форматер с идентификатором custom будет возвращен вызовом:

my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)

Ключ '()' был использован как специальный ключ, потому что он не является допустимым именем ключевого параметра и, следовательно, не будет конфликтовать с именами ключевых аргументов, используемых в вызове. '()' также служит мнемоникой, что соответствующее значение — это вызываемый объект.

Доступ к внешним объектам

В некоторых случаях конфигурация должна ссылаться на объекты, внешние по отношению к конфигурации, например sys.stderr. Если словарь конфигурации создаётся с помощью кода Python, это просто, но возникает проблема, когда конфигурация предоставляется через текстовый файл (например, JSON, YAML). В текстовом файле нет стандартного способа отличить sys.stderr от литеральной строки 'sys.stderr'. Для этого различия система конфигурации ищет определённые префиксы в строковых значениях и обрабатывает их особым образом. Например, если литеральная строка 'ext://sys.stderr' предоставляется в качестве значения в конфигурации, тогда ext:// будет удалено, и оставшаяся часть значения будет обработана с помощью стандартных механизмов импорта.

Обработка таких префиксов выполняется аналогично обработке протоколов: существует общий механизм для поиска префиксов, соответствующих регулярному выражению ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$, где, если prefix распознан, suffix обрабатывается в зависимости от префикса, и результат обработки заменяет строковое значение. Если префикс не распознан, строковое значение останется без изменений.

Доступ к внутренним объектам

Помимо внешних объектов, иногда также необходимо ссылаться на объекты в конфигурации. Система конфигурации будет неявно делать это для известных ей объектов. Например, строковое значение 'DEBUG' для level в логгере или обработчике будет автоматически преобразовано в значение logging.DEBUG, а записи handlers, filters и formatter будут принимать идентификатор объекта и разрешать соответствующий целевой объект.

Однако для пользовательских объектов, неизвестных модулю logging, требуется более общий механизм. Например, рассмотрим logging.handlers.MemoryHandler, который принимает аргумент target, являющийся другим обработчиком для делегирования. Поскольку система уже знает об этом классе, то в конфигурации заданный target должен быть просто идентификатором объекта соответствующего целевого обработчика, и система найдет обработчик по идентификатору. Однако, если пользователь определяет my.package.MyHandler с обработчиком alternate, система конфигурации не будет знать, что alternate относится к обработчику. Для этого общий механизм разрешения позволяет пользователю указать:

handlers:
  file:
    # configuration of file handler goes here

  custom:
    (): my.package.MyHandler
    alternate: cfg://handlers.file

Литеральная строка 'cfg://handlers.file' будет разрешена аналогичным образом, как строки с префиксом ext://, но будет искать в самой конфигурации, а не в пространстве имён. Механизм позволяет получить доступ через точку или по индексу, аналогично тому, что предоставляет str.format. Таким образом, учитывая следующий фрагмент:

handlers:
  email:
    class: logging.handlers.SMTPHandler
    mailhost: localhost
    fromaddr: my_app@domain.tld
    toaddrs:
      - support_team@domain.tld
      - dev_team@domain.tld
    subject: Houston, we have a problem.

в конфигурации строка 'cfg://handlers' будет разрешена до словаря с ключом handlers, строка 'cfg://handlers.email будет разрешена до словаря с ключом email в словаре handlers и так далее. Строка 'cfg://handlers.email.toaddrs[1] будет разрешена до 'dev_team.domain.tld', а строка 'cfg://handlers.email.toaddrs[0]' будет разрешена до значения 'support_team@domain.tld'. Значение subject можно получить, используя либо 'cfg://handlers.email.subject', или, что эквивалентно, 'cfg://handlers.email[subject]'. Последний вариант необходимо использовать только в том случае, если ключ содержит пробелы или символы, не являющиеся алфавитно-цифровыми. Если значение индекса состоит только из десятичных цифр, попытка доступа будет произведена с использованием соответствующего целочисленного значения, с возвратом к строковому значению при необходимости.

Учитывая строку cfg://handlers.myhandler.mykey.123, она будет разрешена до config_dict['handlers']['myhandler']['mykey']['123']. Если строка задана как cfg://handlers.myhandler.mykey[123], система попытается получить значение из config_dict['handlers']['myhandler']['mykey'][123], и вернёт config_dict['handlers']['myhandler']['mykey']['123'] в случае неудачи.

Разрешение импорта и пользовательские импортёры

Разрешение импорта по умолчанию использует встроенную функцию __import__() для выполнения импорта. Возможно, вам потребуется заменить её собственным механизмом импорта. В этом случае вы можете заменить атрибут importer у DictConfigurator или его суперкласса, класса BaseConfigurator. Однако необходимо быть внимательными из-за того, как функции вызываются из классов через дескрипторы. Если вы используете вызываемый Python-объект для выполнения импорта, а хотите определить его на уровне класса, а не экземпляра, необходимо обернуть его в staticmethod(). Например:

from importlib import import_module
from logging.config import BaseConfigurator

BaseConfigurator.importer = staticmethod(import_module)

Вам не нужно обертывать в staticmethod(), если вы устанавливаете вызываемый импорт на экземпляре конфигуратора.

Формат файла конфигурации

Формат файла конфигурации, понимаемый fileConfig(), основан на функциональности configparser. Файл должен содержать разделы, называемые [loggers], [handlers] и [formatters], которые по имени идентифицируют сущности каждого типа, определённые в файле. Для каждой такой сущности есть отдельный раздел, определяющий, как эта сущность настроена. Таким образом, для логгера с именем log01 в разделе [loggers], соответствующие данные конфигурации хранятся в разделе [logger_log01]. Аналогично, обработчик с именем hand01 в разделе [handlers] будет иметь свою конфигурацию, хранящуюся в разделе [handler_hand01], а форматтер с именем form01 в разделе [formatters] будет иметь свою конфигурацию, указанную в разделе [formatter_form01]. Конфигурация корневого логгера должна быть указана в разделе [logger_root].

Примечание

API fileConfig() старше API dictConfig() и не предоставляет функциональность для покрытия некоторых аспектов ведения логов. Например, вы не можете настроить объекты Filter, которые обеспечивают фильтрацию сообщений за пределами простых целочисленных уровней, используя fileConfig(). Если вам необходимо иметь экземпляры Filter в вашей конфигурации ведения логов, вам нужно использовать dictConfig(). Обратите внимание, что будущие улучшения функциональности конфигурации будут добавлены в dictConfig(), поэтому стоит рассмотреть переход на эту более новую API, когда это удобно.

Примеры этих разделов в файле приведены ниже.

[loggers]
keys=root,log02,log03,log04,log05,log06,log07

[handlers]
keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09

[formatters]
keys=form01,form02,form03,form04,form05,form06,form07,form08,form09

Корневой логгер должен указать уровень и список обработчиков. Пример раздела корневого логгера приведён ниже.

[logger_root]
level=NOTSET
handlers=hand01

Запись level может быть одной из DEBUG, INFO, WARNING, ERROR, CRITICAL или NOTSET. Только для корневого логгера, NOTSET означает, что все сообщения будут записаны в лог. Значения уровня оцениваются в контексте пространства имён пакета logging.

Запись handlers представляет собой список имён обработчиков, разделённых запятыми, которые должны появиться в разделе [handlers]. Эти имена должны присутствовать в разделе [handlers] и иметь соответствующие разделы в файле конфигурации.

Для логгеров, отличных от корневого логгера, требуется дополнительная информация. Это показано на следующем примере.

[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser

Записи level и handlers интерпретируются так же, как и для корневого логгера, за исключением того, что если уровень некорневого логгера указан как NOTSET, система обращается к логгерам выше по иерархии, чтобы определить эффективный уровень логгера. Запись propagate устанавливается в 1, чтобы указать, что сообщения должны распространяться на обработчики выше по иерархии логгера от этого логгера, или в 0, чтобы указать, что сообщения не распространяются на обработчики выше по иерархии. Запись qualname представляет собой иерархическое имя канала логгера, то есть имя, используемое приложением для получения логгера.

Разделы, которые указывают конфигурацию обработчика, иллюстрируются следующим образом.

[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)

Запись class указывает класс обработчика (определяемый eval() в пространстве имён пакета logging). Запись level интерпретируется так же, как и для логгеров, а NOTSET означает «логировать всё».

Запись formatter указывает имя ключа форматтера для этого обработчика. Если пусто, используется форматтер по умолчанию (logging._defaultFormatter). Если имя указано, оно должно появиться в разделе [formatters] и иметь соответствующий раздел в файле конфигурации.

Запись args, при eval() оценке в контексте пространства имён пакета logging, представляет собой список аргументов конструктора для класса обработчика. Обратитесь к конструкторам соответствующих обработчиков или к приведённым ниже примерам, чтобы увидеть, как строятся типичные записи. Если не предоставлено, оно по умолчанию равно ().

Необязательная запись kwargs, при eval() оценке в контексте пространства имён пакета logging, представляет собой словарь ключевых аргументов для конструктора класса обработчика. Если не предоставлено, оно по умолчанию равно {}.

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form02
args=('python.log', 'w')

[handler_hand03]
class=handlers.SocketHandler
level=INFO
formatter=form03
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)

[handler_hand04]
class=handlers.DatagramHandler
level=WARN
formatter=form04
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)

[handler_hand05]
class=handlers.SysLogHandler
level=ERROR
formatter=form05
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)

[handler_hand06]
class=handlers.NTEventLogHandler
level=CRITICAL
formatter=form06
args=('Python Application', '', 'Application')

[handler_hand07]
class=handlers.SMTPHandler
level=WARN
formatter=form07
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
kwargs={'timeout': 10.0}

[handler_hand08]
class=handlers.MemoryHandler
level=NOTSET
formatter=form08
target=
args=(10, ERROR)

[handler_hand09]
class=handlers.HTTPHandler
level=NOTSET
formatter=form09
args=('localhost:9022', '/log', 'GET')
kwargs={'secure': True}

Разделы, определяющие конфигурацию форматтера, типизируются следующим образом.

[formatter_form01]
format=F1 %(asctime)s %(levelname)s %(message)s
datefmt=
class=logging.Formatter

Запись format представляет собой строку общего формата, а запись datefmt представляет собой строку формата даты/времени, совместимую с strftime(). Если она пуста, пакет подставляет что-то, что почти эквивалентно указанию строки формата даты '%Y-%m-%d %H:%M:%S'. Этот формат также указывает миллисекунды, которые добавляются к результату использования вышеупомянутой строки формата, с разделителем запятой. Пример времени в этом формате — 2003-01-23 00:29:50,411.

Запись class необязательна. Она указывает имя класса форматтера (как имя модуля и класса с точкой). Этот параметр полезен для создания подкласса Formatter. Подклассы Formatter могут представлять трассировки исключений в расширенном или сокращённом формате.

Примечание

Из-за использования eval(), как описано выше, существуют потенциальные риски безопасности, которые возникают при использовании listen() для отправки и получения конфигураций через сокеты. Риски ограничены случаями, когда несколько пользователей без взаимного доверия запускают код на одной машине; см. документацию listen() для получения дополнительной информации.

См. также

Module logging

Ссылка на API модуля ведения логов.

Module logging.handlers

Полезные обработчики, включённые в модуль ведения логов.

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/logging.config.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API