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, так как это позволяет сохранить старое поведение обратной совместимости. Это поведение заключается в отключении всех существующих логгеров, кроме корневого, если они или их предки не указаны явно в конфигурации ведения журнала.
-
fname – Имя файла или объект-подобный файлу, или экземпляр, полученный от
Изменено в версии 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в отправляемой конфигурации.
Учёт мер безопасности
Функциональность настройки логирования пытается предложить удобство, и отчасти это достигается возможностью конвертировать текст в файлах конфигурации в объекты 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, что означает, что указанная конфигурация заменяет существующую конфигурацию с теми же семантическими правилами, что и у существующего APIfileConfig().Если указанное значение равно
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() для получения дополнительной информации.
См. также
-
Modulelogging -
Ссылка на API модуля ведения логов.
-
Modulelogging.handlers -
Полезные обработчики, включённые в модуль ведения логов.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/library/logging.config.html