logging.config
— Конфигурация журналирования¶
Kod źródłowy: 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()
Например, подкласс
DictConfigurator
может вызыватьDictConfigurator.__init__()
в своем собственном__init__()
, а затем устанавливать собственные префиксы, которые можно будет использовать в последующихconfigure. ` позвони. :attr:`dictConfigClass()
будет привязан к этому новому подклассу, а затемdictConfig()
может быть вызван точно так же, как в ненастроенном состоянии по умолчанию.Dodane w wersji 3.2.
- logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)¶
Читає конфігурацію журналювання з файлу у форматі
configparser
. Формат файлу має бути таким, як описано в Формат файлу конфігурації. Цю функцію можна викликати кілька разів із програми, дозволяючи кінцевому користувачеві вибирати з різних попередньо готових конфігурацій (якщо розробник надає механізм для представлення варіантів і завантаження вибраної конфігурації).Он выдаст
FileNotFoundError
, если файл не существует, иRuntimeError
, если файл недействителен или пуст.- Parametry:
fname – Имя файла, файлоподобный объект или экземпляр, производный от
RawConfigParser
. Если передается экземпляр, производный отRawConfigParser
, он используется как есть. В противном случае создается экземплярConfigParser
, и конфигурация считывается им из объекта, переданного вfname
. Если у него есть методreadline()
, предполагается, что он представляет собой файлоподобный объект и читается с помощьюread_file()
; в противном случае предполагается, что это имя файла и передается вread()
.defaults – В этом аргументе можно указать значения по умолчанию, которые будут переданы в
ConfigParser
.disable_existing_loggers – Если указано значение «False», средства ведения журнала, существующие на момент выполнения этого вызова, остаются включенными. По умолчанию установлено значение True, поскольку это позволяет использовать старое поведение с обратной совместимостью. Такое поведение предназначено для отключения всех существующих средств ведения журнала без полномочий root, если они или их предки явно не указаны в конфигурации ведения журнала.
encoding – Кодування, яке використовується для відкриття файлу, коли fname є назвою файлу.
Zmienione w wersji 3.4: Екземпляр підкласу
RawConfigParser
тепер приймається як значення дляfname
. Це полегшує:Використання файлу конфігурації, де конфігурація журналювання є лише частиною загальної конфігурації програми.
Використання конфігурації, зчитаної з файлу, а потім зміненої програмою-користувачем (наприклад, на основі параметрів командного рядка або інших аспектів середовища виконання) перед передачею в
fileConfig
.
Zmienione w wersji 3.10: Добавлен параметр encoding.
Zmienione w wersji 3.12: Исключение будет выдано, если предоставленный файл не существует, является недействительным или пустым.
- 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)
.Informacja
Оскільки частини конфігурації передаються через
eval()
, використання цієї функції може піддати користувачам ризик безпеки. Хоча функція прив’язується лише до сокета наlocalhost
і тому не приймає з’єднання з віддалених машин, існують сценарії, коли ненадійний код може запускатися під обліковим записом процесу, який викликаєlisten()
. Зокрема, якщо процес, який викликаєlisten()
, виконується на багатокористувацькій машині, де користувачі не можуть довіряти один одному, тоді зловмисник може організувати запуск практично довільного коду в процесі користувача-жертви, просто підключившись до жертвиlisten()
сокет і надсилання конфігурації, яка запускає будь-який код, який зловмисник хоче виконати в процесі жертви. Це особливо легко зробити, якщо використовується стандартний порт, але не важко, навіть якщо використовується інший порт. Щоб уникнути цього ризику, використовуйте аргументverify
дляlisten()
, щоб запобігти застосуванню нерозпізнаних конфігурацій.Zmienione w wersji 3.4: Додано аргумент
перевірити
.Informacja
Якщо ви хочете надіслати конфігурації прослухувачу, які не вимикають існуючі реєстратори, вам потрібно буде використовувати формат JSON для конфігурації, яка використовуватиме
dictConfig()
для конфігурації. Цей метод дозволяє вказатиdisable_existing_loggers
якFalse
у конфігурації, яку ви надсилаєте.
Міркування безпеки¶
Функціональність конфігурації журналювання намагається запропонувати зручність, і частково це робиться, пропонуючи можливість перетворювати текст у конфігураційних файлах на об’єкти Python, які використовуються в конфігурації журналювання - наприклад, як описано в Визначені користувачем об’єкти. Однак ці самі механізми (імпорт викликів із визначених користувачем модулів і виклик їх із параметрами з конфігурації) можна використовувати для виклику будь-якого коду, який вам подобається, і з цієї причини ви повинні поводитися з конфігураційними файлами з ненадійних джерел з надзвичайною обережністю і переконайтеся, що нічого поганого не станеться, якщо ви їх завантажите, перш ніж завантажувати їх.
Схема словника конфігурації¶
Опис конфігурації журналювання вимагає переліку різних об’єктів для створення та зв’язків між ними; наприклад, ви можете створити обробник під назвою „console”, а потім сказати, що реєстратор під назвою „startup” надсилатиме свої повідомлення до обробника „console”. Ці об’єкти не обмежуються об’єктами, наданими модулем logging
, оскільки ви можете написати власний формататор або клас обробника. Параметри цих класів можуть також потребувати включення зовнішніх об’єктів, таких як sys.stderr
. Синтаксис для опису цих об’єктів і з’єднань визначено в Об’єктні зв’язки нижче.
Подробиці схеми словника¶
Словник, переданий до dictConfig()
, повинен містити такі ключі:
version - має бути встановлено ціле значення, що представляє версію схеми. Єдиним дійсним значенням наразі є 1, але наявність цього ключа дозволяє схемі розвиватися, зберігаючи зворотну сумісність.
Усі інші ключі необов’язкові, але якщо вони присутні, вони інтерпретуватимуться, як описано нижче. У всіх випадках, наведених нижче, де згадується „налаштування dict”, буде перевірено наявність спеціального ключа '()''
, щоб побачити, чи потрібен власний екземпляр. Якщо так, механізм, описаний у Визначені користувачем об’єкти нижче, використовується для створення екземпляра; інакше контекст використовується для визначення того, що створити екземпляр.
formatters - відповідне значення буде dict, у якому кожен ключ є ідентифікатором formatter, а кожне значення є dict, що описує, як налаштувати відповідний екземпляр
Formatter
.У диктофоні налаштування шукаються наступні додаткові ключі, які відповідають аргументам, переданим для створення об’єкта
Formatter
:format
datefmt
style
validate
(починаючи з версії >=3.8)defaults
(since version >=3.12)
Необов’язковий ключ
class
вказує на ім’я класу форматера (у вигляді модуля та імені класу з крапками). Аргументи створення екземпляра такі ж, як і дляFormatter
, тому цей ключ найбільш корисний для створення екземпляра налаштованого підкласуFormatter
. Наприклад, альтернативний клас може представляти трасування винятків у розгорнутому або скороченому форматі. Якщо ваш форматувальник вимагає інших або додаткових ключів конфігурації, ви повинні використовувати Визначені користувачем об’єкти.filters — відповідне значення буде диктовим словом, у якому кожен ключ є ідентифікатором фільтра, а кожне значення — диктовим кодом, що описує, як налаштувати відповідний екземпляр фільтра.
Dict конфігурації шукається за ключем
name
(за замовчуванням порожній рядок), і це використовується для створення екземпляраlogging.Filter
.обробники – відповідним значенням буде dict, у якому кожен ключ є ідентифікатором обробника, а кожне значення є dict, що описує, як налаштувати відповідний екземпляр Handler.
У диктофоні налаштування виконується пошук таких ключів:
клас
(обов’язковий). Це повна назва класу обробника.рівень
(необов’язково). Рівень обробника.форматувальник
(необов’язковий). Ідентифікатор форматера для цього обробника.фільтри
(необов’язково). Список ідентифікаторів фільтрів для цього обробника.Zmienione w wersji 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
(необов’язковий). Налаштування розповсюдження реєстратора.фільтри
(необов’язково). Список ідентифікаторів фільтрів для цього реєстратора.Zmienione w wersji 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'
}
dan:
{
'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)
Ostrzeżenie
Значения таких ключей, как bar
, spam
и ответ
в приведенном выше примере не должны быть словарями конфигурации или ссылками, такими как cfg://foo
или ext: //bar
, потому что они не будут обрабатываться механизмом настройки, а будут переданы вызываемому объекту как есть.
Ключ '()'
використовувався як спеціальний ключ, оскільки він не є дійсним ім’ям параметра ключового слова, і тому не буде конфліктувати з назвами аргументів ключового слова, які використовуються у виклику. '()'
також служить мнемонічною ознакою того, що відповідне значення є викликом.
Zmienione w wersji 3.11: Член filters
в handlers
и loggers
может принимать экземпляры фильтров в дополнение к идентификаторам.
您还可以指定一个特殊的键 '.'
,它的值是属性名到值的映射。 如果找到,在返回用户定义对象之前,将在该对象上设置指定的属性。 因此,使用以下配置:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42,
'.' {
'foo': 'bar',
'baz': 'bozz'
}
}
возвращаемый форматтер будет иметь атрибут foo
, установленный в 'bar'
, а атрибут baz
установлен в 'bozz'
.
Ostrzeżenie
Значения таких атрибутов, как foo
и baz
в приведенном выше примере, не должны быть словарями конфигурации или ссылками, такими как cfg://foo
или ext://bar
, поскольку они не будут обрабатываться механизмом настройки, а будут установлены как значения атрибутов как есть.
Порядок настройки обработчика¶
处理器按其键的字母顺序进行配置,而已配置的处理器将替换配置方案内部 handlers
字典(的一个工作副本)中的配置字典。 如果你使用 cfg://handlers.foo
这样的构造,那么在初始状态下 handlers['foo']
会指向具名为 foo
的处理器的配置字典,随后(一旦配置了该处理器)它将指向已配置的处理器实例。 因此,cfg://handlers.foo
可以解析为一个字典或处理器实例。 通常来说,对于带依赖的处理器采用在它们所依赖的任何处理器完成配置 之后 再进行配置的方式来命名处理器是一种明智的做法;这将允许使用 cfg://handlers.foo
这样的构造来配置依赖于处理器 foo
的处理器。 如果这个带依赖的处理器被具名为 bar
,则会导致问题,因为 bar
的配置将在 foo
的配置之前被尝试使用,而 foo
将尚未配置完成。 但是,如果带依赖的处理器被具名为 foobar
,则它将在 foo
之后被配置,结果就是 cfg://handlers.foo
将被解析为已配置的处理器 foo
,而不是其配置字典。
Доступ до зовнішніх об’єктів¶
Бувають випадки, коли конфігурація потребує посилання на об’єкти, зовнішні щодо конфігурації, наприклад 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.
в конфигурации строка 'cfg://handlers'
будет разрешаться в словарь с ключом handlers
, строка 'cfg://handlers.email
будет разрешаться в словарь с ключом handlers
. ключ 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()
, якщо ви встановлюєте виклик імпорту в примірнику конфігуратора.
Настройка QueueHandler и QueueListener¶
Если вы хотите настроить QueueHandler
, учитывая, что он обычно используется вместе с QueueListener
, вы можете настроить оба вместе. После настройки экземпляр QueueListener будет доступен как атрибут listener
созданного обработчика, а он, в свою очередь, будет доступен вам с помощью getHandlerByName()
и передав имя, которое вы использовали для QueueHandler`` в вашей конфигурации. Схема словаря для настройки пары показана в примере фрагмента YAML ниже.
handlers:
qhand:
class: logging.handlers.QueueHandler
queue: my.module.queue_factory
listener: my.package.CustomListener
handlers:
- hand_name_1
- hand_name_2
...
Ключи queue
и listener
являются необязательными.
Если присутствует ключ очереди, соответствующее значение может быть одним из следующих:
Объект, реализующий общедоступный API
Queue.put_nowait
иQueue.get
. Например, это может быть реальный экземплярqueue.Queue
или его подкласса, или прокси, полученныйmultiprocessing.managers.SyncManager.Queue()
.Конечно, это возможно только в том случае, если вы создаете или изменяете словарь конфигурации в коде.
Строка, которая преобразуется в вызываемый объект, который при вызове без аргументов возвращает экземпляр очереди для использования. Этот вызываемый объект может быть подклассом
queue.Queue
или функцией, которая возвращает подходящий экземпляр очереди, напримерmy.module.queue_factory()
.Дикт с ключом
'()'
, который создается обычным способом, как описано в Визначені користувачем об’єкти. Результатом этой конструкции должен быть экземплярqueue.Queue
.
Если ключ queue
отсутствует, создается и используется стандартный неограниченный экземпляр queue.Queue
.
Если присутствует ключ listener
, соответствующее значение может быть одним из следующих:
Подкласс
logging.handlers.QueueListener
. Конечно, это возможно только в том случае, если вы создаете или изменяете словарь конфигурации в коде.Строка, которая разрешается в класс, который является подклассом QueueListener, например my.package.CustomListener.
Дикт с ключом
'()'
, который создается обычным способом, как описано в Визначені користувачем об’єкти. Результатом этой конструкции должен быть вызываемый объект с той же сигнатурой, что и инициализатор QueueListener.
Если ключ listener
отсутствует, используется logging.handlers.QueueListener
.
Значения под ключом handlers — это имена других обработчиков в конфигурации (не показаны в приведенном выше фрагменте), которые будут переданы прослушивателю очереди.
Любые пользовательские классы обработчиков и прослушивателей очереди должны быть определены с теми же сигнатурами инициализации, что и QueueHandler
и QueueListener
.
Dodane w wersji 3.12.
Формат файлу конфігурації¶
Формат файлу конфігурації, який розуміє fileConfig()
, базується на функціях configparser
. Файл має містити розділи під назвою [реєстратори]
, [обробники]
і [formatters]
, які ідентифікують за назвою сутності кожного типу, визначені у файлі. Для кожної такої сутності існує окремий розділ, який визначає, як цю сутність налаштовано. Таким чином, для реєстратора з назвою log01
у розділі [loggers]
відповідні деталі конфігурації зберігаються в розділі [logger_log01]
. Подібним чином конфігурація обробника під назвою hand01
у розділі [handlers]
зберігатиметься в розділі [handler_hand01]
, а програма форматування під назвою form01
у Конфігурація розділу [formatters]
буде вказана в розділі під назвою [formatter_form01]
. Конфігурацію кореневого реєстратора необхідно вказати в розділі під назвою [logger_root]
.
Informacja
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
.
Запис обробники
— це список імен обробників, розділених комами, які повинні з’являтися в розділі [обробники]
. Ці назви мають відображатися в розділі [обробники]
і мати відповідні розділи у файлі конфігурації.
Для реєстраторів, відмінних від кореневого реєстратора, потрібна додаткова інформація. Це ілюструється наступним прикладом.
[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]
і мати відповідний розділ у файлі конфігурації.
Запись args
, когда оценивается в контексте пространства имен пакета logging
, представляет собой список аргументов конструктора для класса-обработчика. Обратитесь к конструкторам соответствующих обработчиков или к примерам ниже, чтобы увидеть, как создаются типичные записи. Если не указано, по умолчанию используется ()
.
Запись args
, когда оценивается в контексте пространства имен пакета 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 %(customfield)s
datefmt=
style=%
validate=True
defaults={'customfield': 'defaultvalue'}
class=logging.Formatter
Аргументи конфігурації форматера такі ж, як і ключі в схемі словника розділ formatters.
Запись defaults
, когда оценивается в контексте пространства имен пакета logging
, представляет собой словарь значений по умолчанию для пользовательских полей форматирования. Если он не указан, по умолчанию используется значение «Нет».
Informacja
Через використання eval()
, як описано вище, існують потенційні ризики для безпеки, які є результатом використання listen()
для надсилання та отримання конфігурацій через сокети. Ризики обмежені тим, що кілька користувачів, які не мають взаємної довіри, запускають код на одній машині; дивіться документацію listen()
для отримання додаткової інформації.
Zobacz także
- Модуль
logging
Довідник API для модуля журналювання.
- Модуль
logging.handlers
Корисні обробники, включені в модуль журналювання.