logging.config — Настройка логгера
Исходный код: Lib/logging/config.py
Этот раздел описывает API для настройки модуля логгирования.
1. Функции настройки
Следующие функции настраивают модуль логгирования. Они находятся в модуле 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()можно будет вызвать точно так же, как и в стандартном, не настраиваемом состоянии.Новое в версии 2.7.
- Значение
-
logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True) -
Читает конфигурацию логгирования из файла в формате
configparserс именем fname. Формат файла должен быть описан в Формат файла конфигурации. Эту функцию можно вызывать несколько раз из приложения, позволяя конечному пользователю выбирать из различных предварительно подготовленных конфигураций (если разработчик предоставит механизм для отображения вариантов и загрузки выбранной конфигурации).- Параметры
-
- defaults – Значения по умолчанию, которые нужно передать в ConfigParser, можно указать в этом аргументе.
-
disable_existing_loggers – Если задано как
False, логгеры, которые существуют во время этого вызова, остаются включёнными. По умолчаниюTrue, так как это позволяет сохранить старое поведение в обратной совместимости. Это поведение заключается в отключении всех существующих логгеров, если они или их предки не указаны явно в конфигурации логгирования.
Изменено в версии 2.6: Добавлен ключевой аргумент
disable_existing_loggers. Раньше существующие логгеры всегда отключались.
-
logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT) -
Запускает сервер сокетов на указанном порту и прослушивает новые конфигурации. Если порт не указан, используется значение по умолчанию модуля
DEFAULT_LOGGING_CONFIG_PORT. Конфигурации логгирования будут отправляться как файл, подходящий для обработки функциейfileConfig(). Возвращает экземплярThread, на котором вы можете вызватьstart()для запуска сервера иjoin()в случае необходимости. Для остановки сервера вызовитеstopListening().Для отправки конфигурации в сокет, прочитайте файл конфигурации и отправьте его в сокет как строку байтов, предваряемую четырёхбайтовой строкой длины, упакованной в двоичном формате с помощью
struct.pack('>L', n).Примечание
Из-за того, что части конфигурации передаются через
eval(), использование этой функции может создать угрозу безопасности. Хотя функция связывается только с сокетом наlocalhost, и поэтому не принимает подключения от удалённых машин, существуют сценарии, в которых неуправляемый код может быть запущен под учётной записью процесса, вызвавшегоlisten(). В частности, если процесс, вызывающийlisten(), выполняется на многопользовательской машине, где пользователи не могут доверять друг другу, то злонамеренный пользователь может организовать запуск произвольного кода в процессе жертвы просто подключившись к сокетуlisten()жертвы и отправив конфигурацию, которая запускает код, который злоумышленник хочет выполнить в процессе жертвы. Это особенно легко сделать, если используется порт по умолчанию, но не сложно даже если используется другой порт.
-
logging.config.stopListening() -
Останавливает сервер прослушивания, созданный с помощью вызова
listen(). Это обычно вызывается перед вызовомjoin()на возвращаемом значении изlisten().
2. Схема словаря конфигурации
Описание конфигурации логгирования требует перечисления различных создаваемых объектов и связей между ними; например, вы можете создать обработчик с именем «консоль», а затем указать, что логгер с именем «запуск» будет отправлять свои сообщения в обработчик «консоль». Эти объекты не ограничиваются объектами, предоставляемыми модулем logging, так как вы можете написать собственный класс форматирования или обработчика. Параметры этих классов также могут потребовать внешние объекты, такие как sys.stderr. Синтаксис для описания этих объектов и связей определён в Связи объектов ниже.
2.1. Подробности схемы словаря
Словарь, переданный dictConfig(), должен содержать следующие ключи:
- version - должен быть установлен в целое число, представляющее версию схемы. В настоящее время единственное допустимое значение равно 1, но наличие этого ключа позволяет схеме эволюционировать, сохраняя обратную совместимость.
Все остальные ключи необязательны, но если они присутствуют, они будут интерпретированы, как описано ниже. Во всех случаях ниже, где упоминается «словарь конфигурации», будет проверяться наличие специального ключа '()' , чтобы определить, требуется ли пользовательская инициализация. В случае необходимости, используется механизм, описанный в Пользовательские объекты ниже; в противном случае контекст используется для определения того, что нужно инициализировать.
-
formatters — соответствующее значение будет словарем, в котором каждый ключ — идентификатор форматировщика, а каждое значение — словарь, описывающий, как настроить соответствующий экземпляр
Formatter.Конфигурирующий словарь ищется по ключам
formatиdatefmt(с значениями по умолчаниюNone) и используется для построения экземпляраFormatter. -
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.
2.2. Инкрементная конфигурация
Трудно обеспечить полную гибкость для инкрементной конфигурации. Например, поскольку такие объекты, как фильтры и форматировщики, являются анонимными, после настройки конфигурации невозможно сослаться на такие анонимные объекты при дополнении конфигурации.
Кроме того, нет веских причин для произвольного изменения графа объектов логгеров, обработчиков, фильтров, форматировщиков во время выполнения после настройки конфигурации; уровень детализации логгеров и обработчиков можно контролировать только установкой уровней (и, в случае с логгерами, флагов распространения). Произвольное изменение графа объектов безопасным способом проблематично в многопоточной среде; хотя это и не невозможно, но преимущества не стоят сложности, которую это добавляет к реализации.
Таким образом, когда ключ incremental в словаре конфигурации присутствует и имеет значение True, система полностью проигнорирует любые записи formatters и filters, и обработает только настройки level в записях handlers, и настройки level и propagate в записях loggers и root.
Использование значения в словаре конфигурации позволяет отправлять конфигурации по сети как закодированные словари по сокету получателю. Таким образом, уровень детализации логов долго работающего приложения можно изменять со временем без необходимости остановки и перезапуска приложения.
2.3. Связи объектов
Схема описывает набор объектов логгирования — логгеры, обработчики, форматировщики, фильтры — которые связаны друг с другом в графе объектов. Таким образом, схема должна представлять связи между объектами. Например, скажем, что после настройки определённый логгер подключен к определённому обработчику. Для целей этого обсуждения мы можем сказать, что логгер представляет собой источник, а обработчик — место назначения связи между двумя объектами. Конечно, в настроенных объектах это представлено тем, что логгер содержит ссылку на обработчик. В словаре конфигурации это делается путём присвоения каждому объекту-получателю уникального идентификатора и последующего использования этого идентификатора в конфигурации объекта-источника для указания существования связи между объектом-источником и объектом-получателем с этим идентификатором.
Итак, например, рассмотрите следующий фрагмент 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.
2.4. Пользовательские объекты
Схема поддерживает пользовательские объекты для обработчиков, фильтров и форматировщиков. (Логгеры не должны иметь разные типы для разных экземпляров, поэтому в этой схеме конфигурации нет поддержки пользовательских классов логгеров.)
Объекты, подлежащие настройке, описываются словарями, которые подробно описывают их настройку. В некоторых местах система логгирования сможет вывести из контекста, как должен быть создан объект, но когда нужно создать пользовательский объект, система не будет знать, как это сделать. Чтобы обеспечить полную гибкость для создания пользовательских объектов, пользователю необходимо предоставить «фабрику» — вызываемую функцию, которая вызывается со словарем конфигурации и возвращает созданный объект. Это обозначается абсолютным импортным путем к фабрике, предоставленным по специальному ключу '()'.
Вот конкретный пример:
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)
Ключ '()' используется в качестве специального ключа, потому что он не является допустимым именем ключевого параметра и поэтому не будет конфликтовать с именами ключевых аргументов, используемых в вызове. Ключ '()' также служит мнемоникой, указывающей, что соответствующее значение является вызываемой функцией.
2.5. Доступ к внешним объектам
Бывают случаи, когда конфигурация должна ссылаться на объекты, внешние по отношению к самой конфигурации, например sys.stderr. Если словарь конфигурации создаётся с помощью кода Python, это легко, но проблема возникает, когда конфигурация предоставляется через текстовый файл (например, JSON, YAML). В текстовом файле нет стандартного способа отличить sys.stderr от буквальной строки 'sys.stderr'. Чтобы упростить это различие, система конфигурации ищет определённые специальные префиксы в строковых значениях и обрабатывает их особым образом. Например, если в качестве значения конфигурации предоставляется буквальная строка 'ext://sys.stderr', тогда ext:// будет удалено, а остальная часть значения будет обработана с помощью обычных механизмов импорта.
Обработка таких префиксов выполняется аналогично обработке протоколов: существует общий механизм поиска префиксов, соответствующих регулярному выражению ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$, при котором, если prefix распознан, suffix обрабатывается в зависимости от префикса, а результат обработки заменяет строковое значение. Если префикс не распознан, строковое значение остаётся неизменным.
2.6. Доступ к внутренним объектам
Помимо внешних объектов, иногда также необходимо ссылаться на объекты в конфигурации. Это будет сделано неявно системой конфигурации для объектов, о которых она знает. Например, строковое значение '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'] в случае неудачи.
2.7. Разрешение импорта и пользовательские импортеры
Разрешение импорта по умолчанию использует встроенную функцию __import__() для выполнения импорта. Возможно, вам потребуется заменить это собственным механизмом импорта: в таком случае вы можете заменить атрибут importer объекта DictConfigurator или его суперкласса, класса BaseConfigurator. Однако необходимо быть внимательным из-за способа доступа к функциям из классов через дескрипторы. Если вы используете вызываемый объект Python для выполнения импорта и хотите определить его на уровне класса, а не на уровне экземпляра, необходимо обернуть его в staticmethod(). Например:
from importlib import import_module from logging.config import BaseConfigurator BaseConfigurator.importer = staticmethod(import_module)
Вам не нужно обертывать в staticmethod(), если вы устанавливаете вызываемый объект импорта на экземпляре конфигуратора.
3. Формат файла конфигурации
Формат файла конфигурации, понимаемый 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 означает «записывать всё».
Изменено в версии 2.6: Добавлена поддержка разрешения класса обработчика как имени модуля и класса с точкой.
Запись formatter указывает имя ключа форматировщика для этого обработчика. Если она пуста, используется форматировщик по умолчанию (logging._defaultFormatter). Если имя указано, оно должно присутствовать в разделе [formatters] и иметь соответствующий раздел в файле конфигурации.
Запись args, при 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')
[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')
Примеры разделов, задающих конфигурацию форматировщиков, приведены ниже.
[formatter_form01] format=F1 %(asctime)s %(levelname)s %(message)s datefmt= class=logging.Formatter
Запись format — это строка общего формата, а запись datefmt — строка формата даты/времени, совместимая с strftime(). Если она пустая, пакет подставляет формат даты/времени ISO8601, что почти эквивалентно указанию строки формата даты '%Y-%m-%d %H:%M:%S'. Формат ISO8601 также указывает миллисекунды, которые добавляются к результату использования вышеуказанной строки формата с разделителем запятой. Пример времени в формате ISO8601: 2003-01-23 00:29:50,411.
Запись class необязательна. Она указывает имя класса форматировщика (в виде модуля и имени класса, разделенных точкой). Этот параметр полезен для создания экземпляра подкласса Formatter. Подклассы Formatter могут представлять отладочную информацию об исключениях в развернутом или свёрнутом формате.
Примечание
Из-за использования eval(), как описано выше, существуют потенциальные риски безопасности, связанные с использованием listen() для отправки и получения конфигураций через сокеты. Риски ограничены случаями, когда несколько пользователей без взаимного доверия выполняют код на одной машине; см. документацию listen() для получения дополнительной информации.
См. также
-
Modulelogging -
Справочная информация по модулю ведения журнала.
-
Modulelogging.handlers -
Полезные обработчики, включенные в модуль ведения журнала.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/logging.config.html