Spec-Zone.ru › Python 3.9

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().

Учёт мер безопасности

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

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

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

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

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

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

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

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

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

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

  • 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.9/library/logging.config.html

Spec-Zone.ru

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