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 call DictConfigurator.__init__() in its own __init__(), then set up custom prefixes which would be usable in the subsequent configure() call. dictConfigClass would be bound to this new subclass, and then dictConfig() 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 and RuntimeError if the file is invalid or empty.

Параметри:
  • fname – A filename, or a file-like object, or an instance derived from RawConfigParser. If a RawConfigParser-derived instance is passed, it is used as is. Otherwise, a ConfigParser is instantiated, and the configuration read by it from the object passed in fname. If that has a readline() method, it is assumed to be a file-like object and read using read_file(); otherwise, it is assumed to be a filename and passed to read().

  • 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 is True 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 у конфігурації, яку ви надсилаєте.

logging.config.stopListening()

Зупиняє сервер прослуховування, створений за допомогою виклику listen(). Це зазвичай викликається перед викликом join() для значення, яке повертає listen().

Міркування безпеки

Функціональність конфігурації журналювання намагається запропонувати зручність, і частково це робиться, пропонуючи можливість перетворювати текст у конфігураційних файлах на об’єкти 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, що означає, що вказана конфігурація замінює існуючу конфігурацію з тією самою семантикою, яку використовує існуючий API fileConfig().

    Якщо вказане значення 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:

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 the QueueListener 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

Корисні обробники, включені в модуль журналювання.