Spec-Zone.ru › Python 3.7

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.
END_OF_DOCUMENT_MARKER
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 в отправляемой вами конфигурации.

logging.config.stopListening()

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

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

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

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

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

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

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

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

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

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

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

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

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

    • 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 - соответствующее значение будет словарем, в котором каждый ключ — имя логгера, а каждое значение — словарь, описывающий, как настроить соответствующий экземпляр логгера.

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

    • 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

Справочная информация по модулю ведения логов.

Module logging.handlers

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

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

Spec-Zone.ru

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