logging.config
— Logging configuration¶
Вихідний код: Lib/logging/config.py
У цьому розділі описано API для налаштування модуля журналювання.
Функції конфігурації¶
Наступні функції налаштовують модуль журналювання. Вони знаходяться в модулі logging.config
. Їхнє використання необов’язкове — ви можете налаштувати модуль журналювання за допомогою цих функцій або викликом основного API (визначеного в самому logging
) і визначення обробників, які оголошуються або в logging
, або logging.handlers
.
- logging.config.dictConfig(config)¶
Бере конфігурацію журналювання зі словника. Вміст цього словника описано в Схема словника конфігурації нижче.
Якщо під час налаштування буде виявлено помилку, ця функція викличе
ValueError
,TypeError
,AttributeError
абоImportError
із відповідним описовим повідомленням. Нижче наведено (можливо, неповний) список умов, які викличуть помилку:Рівень
, який не є рядком або є рядком, що не відповідає фактичному рівню реєстрації.Значення
розповсюдження
, яке не є логічним.Ідентифікатор, який не має відповідного адресата.
Під час інкрементного виклику виявлено ідентифікатор неіснуючого обробника.
Недійсне ім’я реєстратора.
Нездатність вирішити внутрішній або зовнішній об’єкт.
Розбір виконується класом
DictConfigurator
, конструктор якого передає словник, який використовується для налаштування, і має методconfigure()
. Модульlogging.config
має викликаний атрибутdictConfigClass
, який початково встановлено наDictConfigurator
. Ви можете замінити значенняdictConfigClass
відповідною власною реалізацією.dictConfig()
викликаєdictConfigClass
, передаючи вказаний словник, а потім викликає методconfigure()
для повернутого об’єкта, щоб застосувати конфігурацію:def dictConfig(config): dictConfigClass(config).configure()
For example, a subclass of
DictConfigurator
could callDictConfigurator.__init__()
in its own__init__()
, then set up custom prefixes which would be usable in the subsequentconfigure()
call.dictConfigClass
would be bound to this new subclass, and thendictConfig()
could be called exactly as in the default, uncustomized state.Added in version 3.2.
- logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)¶
Читає конфігурацію журналювання з файлу у форматі
configparser
. Формат файлу має бути таким, як описано в Формат файлу конфігурації. Цю функцію можна викликати кілька разів із програми, дозволяючи кінцевому користувачеві вибирати з різних попередньо готових конфігурацій (якщо розробник надає механізм для представлення варіантів і завантаження вибраної конфігурації).It will raise
FileNotFoundError
if the file doesn’t exist andRuntimeError
if the file is invalid or empty.- Параметри:
fname – A filename, or a file-like object, or an instance derived from
RawConfigParser
. If aRawConfigParser
-derived instance is passed, it is used as is. Otherwise, aConfigParser
is instantiated, and the configuration read by it from the object passed infname
. If that has areadline()
method, it is assumed to be a file-like object and read usingread_file()
; otherwise, it is assumed to be a filename and passed toread()
.defaults – Defaults to be passed to the
ConfigParser
can be specified in this argument.disable_existing_loggers – If specified as
False
, loggers which exist when this call is made are left enabled. The default isTrue
because this enables old behaviour in a backward-compatible way. This behaviour is to disable any existing non-root loggers unless they or their ancestors are explicitly named in the logging configuration.encoding – Кодування, яке використовується для відкриття файлу, коли fname є назвою файлу.
Змінено в версії 3.4: Екземпляр підкласу
RawConfigParser
тепер приймається як значення дляfname
. Це полегшує:Використання файлу конфігурації, де конфігурація журналювання є лише частиною загальної конфігурації програми.
Використання конфігурації, зчитаної з файлу, а потім зміненої програмою-користувачем (наприклад, на основі параметрів командного рядка або інших аспектів середовища виконання) перед передачею в
fileConfig
.
Змінено в версії 3.10: Added the encoding parameter.
Змінено в версії 3.12: An exception will be thrown if the provided file doesn’t exist or is invalid or empty.
- 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: Додано аргумент
перевірити
.Примітка
Якщо ви хочете надіслати конфігурації прослухувачу, які не вимикають існуючі реєстратори, вам потрібно буде використовувати формат JSON для конфігурації, яка використовуватиме
dictConfig()
для конфігурації. Цей метод дозволяє вказатиdisable_existing_loggers
якFalse
у конфігурації, яку ви надсилаєте.
Міркування безпеки¶
Функціональність конфігурації журналювання намагається запропонувати зручність, і частково це робиться, пропонуючи можливість перетворювати текст у конфігураційних файлах на об’єкти Python, які використовуються в конфігурації журналювання - наприклад, як описано в Визначені користувачем об’єкти. Однак ці самі механізми (імпорт викликів із визначених користувачем модулів і виклик їх із параметрами з конфігурації) можна використовувати для виклику будь-якого коду, який вам подобається, і з цієї причини ви повинні поводитися з конфігураційними файлами з ненадійних джерел з надзвичайною обережністю і переконайтеся, що нічого поганого не станеться, якщо ви їх завантажите, перш ніж завантажувати їх.
Схема словника конфігурації¶
Опис конфігурації журналювання вимагає переліку різних об’єктів для створення та зв’язків між ними; наприклад, ви можете створити обробник під назвою «console», а потім сказати, що реєстратор під назвою «startup» надсилатиме свої повідомлення до обробника «console». Ці об’єкти не обмежуються об’єктами, наданими модулем logging
, оскільки ви можете написати власний формататор або клас обробника. Параметри цих класів можуть також потребувати включення зовнішніх об’єктів, таких як sys.stderr
. Синтаксис для опису цих об’єктів і з’єднань визначено в Об’єктні зв’язки нижче.
Подробиці схеми словника¶
Словник, переданий до dictConfig()
, повинен містити такі ключі:
version - має бути встановлено ціле значення, що представляє версію схеми. Єдиним дійсним значенням наразі є 1, але наявність цього ключа дозволяє схемі розвиватися, зберігаючи зворотну сумісність.
Усі інші ключі необов’язкові, але якщо вони присутні, вони інтерпретуватимуться, як описано нижче. У всіх випадках, наведених нижче, де згадується «налаштування dict», буде перевірено наявність спеціального ключа '()''
, щоб побачити, чи потрібен власний екземпляр. Якщо так, механізм, описаний у Визначені користувачем об’єкти нижче, використовується для створення екземпляра; інакше контекст використовується для визначення того, що створити екземпляр.
formatters - відповідне значення буде dict, у якому кожен ключ є ідентифікатором formatter, а кожне значення є dict, що описує, як налаштувати відповідний екземпляр
Formatter
.У диктофоні налаштування шукаються наступні додаткові ключі, які відповідають аргументам, переданим для створення об’єкта
Formatter
:формат
datefmt
стиль
validate
(починаючи з версії >=3.8)defaults
(since version >=3.12)
Необов’язковий ключ
class
вказує на ім’я класу форматера (у вигляді модуля та імені класу з крапками). Аргументи створення екземпляра такі ж, як і дляFormatter
, тому цей ключ найбільш корисний для створення екземпляра налаштованого підкласуFormatter
. Наприклад, альтернативний клас може представляти трасування винятків у розгорнутому або скороченому форматі. Якщо ваш форматувальник вимагає інших або додаткових ключів конфігурації, ви повинні використовувати Визначені користувачем об’єкти.filters — відповідне значення буде диктовим словом, у якому кожен ключ є ідентифікатором фільтра, а кожне значення — диктовим кодом, що описує, як налаштувати відповідний екземпляр фільтра.
Dict конфігурації шукається за ключем
name
(за замовчуванням порожній рядок), і це використовується для створення екземпляраlogging.Filter
.обробники – відповідним значенням буде dict, у якому кожен ключ є ідентифікатором обробника, а кожне значення є dict, що описує, як налаштувати відповідний екземпляр Handler.
У диктофоні налаштування виконується пошук таких ключів:
клас
(обов’язковий). Це повна назва класу обробника.рівень
(необов’язково). Рівень обробника.форматувальник
(необов’язковий). Ідентифікатор форматера для цього обробника.фільтри
(необов’язково). Список ідентифікаторів фільтрів для цього обробника.Змінено в версії 3.11:
filters
can take filter instances in addition to ids.
Усі інші ключі передаються як аргументи ключового слова до конструктора обробника. Наприклад, враховуючи фрагмент:
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 - відповідне значення буде dict, у якому кожен ключ є іменем logger, а кожне значення є dict, що описує, як налаштувати відповідний екземпляр Logger.
У диктофоні налаштування виконується пошук таких ключів:
рівень
(необов’язково). Рівень лісоруба.propagate
(необов’язковий). Налаштування розповсюдження реєстратора.фільтри
(необов’язково). Список ідентифікаторів фільтрів для цього реєстратора.Змінено в версії 3.11:
filters
can take filter instances in addition to ids.обробники
(необов’язково). Список ідентифікаторів обробників для цього реєстратора.
Зазначені реєстратори буде налаштовано відповідно до вказаного рівня, розповсюдження, фільтрів і обробників.
root - це буде конфігурація для root logger. Обробка конфігурації відбуватиметься так само, як і для будь-якого реєстратора, за винятком того, що параметр
propagate
не застосовуватиметься.incremental – чи конфігурація має інтерпретуватися як додаткова до існуючої конфігурації. За замовчуванням це значення має значення
False
, що означає, що вказана конфігурація замінює існуючу конфігурацію з тією самою семантикою, яку використовує існуючий APIfileConfig()
.Якщо вказане значення
True
, конфігурація обробляється, як описано в розділі про Інкрементна конфігурація.disable_existing_loggers - чи потрібно вимкнути існуючі некореневі реєстратори. Цей параметр відображає однойменний параметр у
fileConfig()
. Якщо цей параметр відсутній, цей параметр за замовчуванням має значенняTrue
. Це значення ігнорується, якщо incremental має значенняTrue
.
Інкрементна конфігурація¶
Важко забезпечити повну гнучкість для поступової конфігурації. Наприклад, оскільки такі об’єкти, як фільтри та засоби форматування, є анонімними, після налаштування конфігурації неможливо посилатися на такі анонімні об’єкти під час розширення конфігурації.
Крім того, немає переконливих аргументів для довільної зміни графа об’єктів реєстраторів, обробників, фільтрів, форматувальників під час виконання, коли конфігурацію встановлено; докладністю реєстраторів і обробників можна керувати, просто встановлюючи рівні (і, у випадку реєстраторів, позначки поширення). Довільна зміна графа об’єктів у безпечний спосіб проблематична в багатопоточному середовищі; Хоча це не неможливо, переваги не варті складності, яку це додає до впровадження.
Таким чином, коли incremental
ключ конфігураційного dict присутній і True
, система повністю ігноруватиме будь-які formatters
і filters
записи, і оброблятиме лише параметри level
в записах handlers
, а level
і propagate
параметри в loggers
і root
записи.
Використання значення в конфігураційному диктофоні дозволяє надсилати конфігурації по дроту як маріновані диктофони до слухача сокета. Таким чином, докладність журналу тривалої програми може бути змінена з часом без необхідності зупиняти та перезапускати програму.
Об’єктні зв’язки¶
Схема описує набір об’єктів журналювання – реєстратори, обробники, засоби форматування, фільтри – які з’єднані один з одним у графі об’єктів. Таким чином, схема повинна представляти зв’язки між об’єктами. Наприклад, скажіть, що після налаштування певний реєстратор приєднав до нього певний обробник. Для цілей цього обговорення ми можемо сказати, що реєстратор представляє джерело, а обробник — призначення з’єднання між ними. Звичайно, у налаштованих об’єктах це представлено реєстратором, що містить посилання на обробник. У dict конфігурації це робиться шляхом надання кожному об’єкту призначення ідентифікатора, який однозначно ідентифікує його, а потім використання ідентифікатора в конфігурації об’єкта джерела, щоб вказати, що між джерелом і об’єктом призначення існує зв’язок із цим ідентифікатором.
Отже, наприклад, розглянемо наступний фрагмент коду 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
. Ідентифікатори для Formatters і Filters можуть бути будь-якими рядковими значеннями (наприклад, 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)
Попередження
The values for keys such as bar
, spam
and answer
in
the above example should not be configuration dictionaries or references such
as cfg://foo
or ext://bar
, because they will not be processed by the
configuration machinery, but passed to the callable as-is.
Ключ '()'
використовувався як спеціальний ключ, оскільки він не є дійсним ім’ям параметра ключового слова, і тому не буде конфліктувати з назвами аргументів ключового слова, які використовуються у виклику. '()'
також служить мнемонічною ознакою того, що відповідне значення є викликом.
Змінено в версії 3.11: The filters
member of handlers
and loggers
can take
filter instances in addition to ids.
You can also specify a special key '.'
whose value is a
mapping of attribute names to values. If found, the specified attributes will
be set on the user-defined object before it is returned. Thus, with the
following configuration:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42,
'.' {
'foo': 'bar',
'baz': 'bozz'
}
}
the returned formatter will have attribute foo
set to 'bar'
and
attribute baz
set to 'bozz'
.
Попередження
The values for attributes such as foo
and baz
in
the above example should not be configuration dictionaries or references such
as cfg://foo
or ext://bar
, because they will not be processed by the
configuration machinery, but set as attribute values as-is.
Handler configuration order¶
Handlers are configured in alphabetical order of their keys, and a configured
handler replaces the configuration dictionary in (a working copy of) the
handlers
dictionary in the schema. If you use a construct such as
cfg://handlers.foo
, then initially handlers['foo']
points to the
configuration dictionary for the handler named foo
, and later (once that
handler has been configured) it points to the configured handler instance.
Thus, cfg://handlers.foo
could resolve to either a dictionary or a handler
instance. In general, it is wise to name handlers in a way such that dependent
handlers are configured after any handlers they depend on; that allows
something like cfg://handlers.foo
to be used in configuring a handler that
depends on handler foo
. If that dependent handler were named bar
,
problems would result, because the configuration of bar
would be attempted
before that of foo
, and foo
would not yet have been configured.
However, if the dependent handler were named foobar
, it would be configured
after foo
, with the result that cfg://handlers.foo
would resolve to
configured handler foo
, and not its configuration dictionary.
Доступ до зовнішніх об’єктів¶
Бувають випадки, коли конфігурація потребує посилання на об’єкти, зовнішні щодо конфігурації, наприклад sys.stderr
. Якщо dict конфігурації створено за допомогою коду Python, це просто, але проблема виникає, коли конфігурація надається через текстовий файл (наприклад, JSON, YAML). У текстовому файлі немає стандартного способу відрізнити sys.stderr
від літерального рядка 'sys.stderr'
. Щоб полегшити це розрізнення, система конфігурації шукає певні спеціальні префікси в рядкових значеннях і обробляє їх спеціальним чином. Наприклад, якщо літеральний рядок 'ext://sys.stderr'
надається як значення в конфігурації, тоді ext://
буде видалено, а залишок значення оброблено за допомогою звичайних механізмів імпорту.
Обробка таких префіксів виконується аналогічно до обробки протоколів: існує загальний механізм пошуку префіксів, які відповідають регулярному виразу ^(?P <prefix> [a-z]+)://(?P <suffix> .* )$
, таким чином, якщо префікс
розпізнається, суфікс
обробляється залежно від префікса, і результат обробки замінює значення рядка. Якщо префікс не розпізнається, значення рядка залишиться без змін.
Доступ до внутрішніх об’єктів¶
Окрім зовнішніх об’єктів, інколи виникає потреба звертатися до об’єктів у конфігурації. Це буде зроблено неявно системою конфігурації для речей, про які вона знає. Наприклад, рядкове значення 'DEBUG
для level
у реєстраторі або обробнику буде автоматично перетворено на значення logging.DEBUG
, а обробники
, Записи filters
і formatter
прийматимуть ідентифікатор об’єкта та вирішуватимуть відповідний об’єкт призначення.
Однак для визначених користувачем об’єктів, які не відомі модулю logging
, потрібен більш загальний механізм. Наприклад, розглянемо logging.handlers.MemoryHandler
, який приймає аргумент target
, який є іншим обробником для делегування. Оскільки системі вже відомо про цей клас, то в конфігурації даний target
має бути просто ідентифікатором об’єкта відповідного цільового обробника, і система вирішить обробник з ідентифікатора. Проте, якщо користувач визначає my.package.MyHandler
, який має альтернативний
обробник, система конфігурації не знатиме, що альтернативний
посилається на обробник. Для цього загальна система роздільної здатності дозволяє користувачеві вказати:
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.
in the configuration, the string 'cfg://handlers'
would resolve to
the dict with key handlers
, the string 'cfg://handlers.email
would resolve to the dict with key email
in the handlers
dict,
and so on. The string 'cfg://handlers.email.toaddrs[1]
would
resolve to 'dev_team@domain.tld'
and the string
'cfg://handlers.email.toaddrs[0]'
would resolve to the value
'support_team@domain.tld'
. The subject
value could be accessed
using either 'cfg://handlers.email.subject'
or, equivalently,
'cfg://handlers.email[subject]'
. The latter form only needs to be
used if the key contains spaces or non-alphanumeric characters. Please note
that the characters [
and ]
are not allowed in the keys. If an
index value consists only of decimal digits, access will be attempted
using the corresponding integer value, falling back to the string
value if needed.
Якщо вказати рядок 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()
, якщо ви встановлюєте виклик імпорту в примірнику конфігуратора.
Configuring QueueHandler and QueueListener¶
If you want to configure a QueueHandler
, noting that this
is normally used in conjunction with a QueueListener
, you
can configure both together. After the configuration, the QueueListener
instance
will be available as the listener
attribute of
the created handler, and that in turn will be available to you using
getHandlerByName()
and passing the name you have used for the
QueueHandler
in your configuration. The dictionary schema for configuring the pair
is shown in the example YAML snippet below.
handlers:
qhand:
class: logging.handlers.QueueHandler
queue: my.module.queue_factory
listener: my.package.CustomListener
handlers:
- hand_name_1
- hand_name_2
...
The queue
and listener
keys are optional.
If the queue
key is present, the corresponding value can be one of the following:
An object implementing the
Queue.put_nowait
andQueue.get
public API. For instance, this may be an actual instance ofqueue.Queue
or a subclass thereof, or a proxy obtained bymultiprocessing.managers.SyncManager.Queue()
.This is of course only possible if you are constructing or modifying the configuration dictionary in code.
A string that resolves to a callable which, when called with no arguments, returns the queue instance to use. That callable could be a
queue.Queue
subclass or a function which returns a suitable queue instance, such asmy.module.queue_factory()
.A dict with a
'()'
key which is constructed in the usual way as discussed in Визначені користувачем об’єкти. The result of this construction should be aqueue.Queue
instance.
If the queue
key is absent, a standard unbounded queue.Queue
instance is
created and used.
If the listener
key is present, the corresponding value can be one of the following:
A subclass of
logging.handlers.QueueListener
. This is of course only possible if you are constructing or modifying the configuration dictionary in code.A string which resolves to a class which is a subclass of
QueueListener
, such as'my.package.CustomListener'
.A dict with a
'()'
key which is constructed in the usual way as discussed in Визначені користувачем об’єкти. The result of this construction should be a callable with the same signature as theQueueListener
initializer.
If the listener
key is absent, logging.handlers.QueueListener
is used.
The values under the handlers
key are the names of other handlers in the
configuration (not shown in the above snippet) which will be passed to the queue
listener.
Any custom queue handler and listener classes will need to be defined with the same
initialization signatures as QueueHandler
and
QueueListener
.
Added in version 3.12.
Формат файлу конфігурації¶
Формат файлу конфігурації, який розуміє fileConfig()
, базується на функціях configparser
. Файл має містити розділи під назвою [реєстратори]
, [обробники]
і [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
The level
entry can be one of DEBUG, INFO, WARNING, ERROR, CRITICAL
or
NOTSET
. For the root logger only, NOTSET
means that all messages will be
logged. Level values are evaluated in the context of the logging
package’s namespace.
Запис обробники
— це список імен обробників, розділених комами, які повинні з’являтися в розділі [обробники]
. Ці назви мають відображатися в розділі [обробники]
і мати відповідні розділи у файлі конфігурації.
Для реєстраторів, відмінних від кореневого реєстратора, потрібна додаткова інформація. Це ілюструється наступним прикладом.
[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser
Записи level
і handlers
інтерпретуються як для кореневого реєстратора, за винятком того, що якщо рівень некореневого реєстратора вказано як NOTSET
, система консультується з реєстраторами вищого рівня в ієрархії, щоб визначити ефективний рівень логера. Запис пропагувати
має значення 1, щоб вказати, що повідомлення повинні поширюватися до обробників, які знаходяться вище в ієрархії реєстратора, або 0, щоб вказати, що повідомлення не поширюються до обробників, які знаходяться вище в ієрархії. Запис qualname
— це ієрархічна назва каналу реєстратора, тобто ім’я, яке використовується програмою для отримання реєстратора.
Розділи, які визначають конфігурацію обробника, представлені нижче.
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)
Запис class
вказує на клас обробника (як визначено eval()
у просторі імен пакета logging
). level
інтерпретується як для реєстраторів, а NOTSET
означає „зареєструвати все“.
Запис formatter
вказує назву ключа форматера для цього обробника. Якщо пусте, використовується форматування за замовчуванням (logging._defaultFormatter
). Якщо вказано ім’я, воно повинно відображатися в розділі [formatters]
і мати відповідний розділ у файлі конфігурації.
The args
entry, when evaluated in the context of the logging
package’s namespace, is the list of arguments to the constructor for the handler
class. Refer to the constructors for the relevant handlers, or to the examples
below, to see how typical entries are constructed. If not provided, it defaults
to ()
.
The optional kwargs
entry, when evaluated in the context of the
logging
package’s namespace, is the keyword argument dict to the constructor
for the handler class. If not provided, it defaults to {}
.
[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 %(customfield)s
datefmt=
style=%
validate=True
defaults={'customfield': 'defaultvalue'}
class=logging.Formatter
Аргументи конфігурації форматера такі ж, як і ключі в схемі словника розділ formatters.
The defaults
entry, when evaluated in the context of
the logging
package’s namespace, is a dictionary of default values for
custom formatting fields. If not provided, it defaults to None
.
Примітка
Через використання eval()
, як описано вище, існують потенційні ризики для безпеки, які є результатом використання listen()
для надсилання та отримання конфігурацій через сокети. Ризики обмежені тим, що кілька користувачів, які не мають взаємної довіри, запускають код на одній машині; дивіться документацію listen()
для отримання додаткової інформації.
Дивись також
- Модуль
logging
Довідник API для модуля журналювання.
- Модуль
logging.handlers
Корисні обробники, включені в модуль журналювання.