Сообщить об ошибке.

Функция dictConfig() модуля logging.config в Python.

Настройка регистратора logger при помощи словаря.

Синтаксис:

import logging.config

logging.config.dictConfig(config)

Параметры:

  • config - словарь, в котором описана конфигурация регистратора.

Возвращаемое значение:

  • нет

Описание:

Функция logging.config.dictConfig() принимает конфигурацию регистратора из словаря.

Если во время настройки возникает ошибка, то эта функция вызовет ValueError, TypeError, AttributeError или ImportError с соответствующим описательным сообщением. Ниже приведен (возможно, неполный) список условий, которые приведут к ошибке:

  • уровень логирования level, не соответствующей фактическому уровню ведения журнала.
  • значение атрибута propagate объекта Logger, не является логическим.
  • идентификатор, который не имеет соответствующего назначения.
  • во время инкрементного вызова обнаружен несуществующий идентификатор обработчика..
  • неверное имя регистратора.
  • невозможность разрешить внутренний или внешний объект.

Синтаксический анализ выполняется классом DictConfigurator, в конструктор которого передается словарь, используемый для настройки, и имеется метод configure(). Модуль logging.config имеет вызываемый атрибут dictConfigClass, для которого изначально установлено значение DictConfigurator. Можно заменить значение dictConfigClass своей подходящей реализацией.

Класс dictConfig() вызывает dictConfigClass, передавая указанный словарь, а затем вызывает метод configure() возвращаемого объекта, чтобы применить конфигурацию:

def dictConfig(config):
    dictConfigClass(config).configure()

Например, подкласс DictConfigurator может вызывать DictConfigurator.__init__() в своем собственном __init__(), а затем настраивать пользовательские префиксы, которые будут использоваться в последующем вызове configure(). DictConfigClass будет привязан к этому новому подклассу, а затем dictConfig() может быть вызван точно так же, как и в нестандартном состоянии по умолчанию.

Детали схемы словаря конфигурации.

Описание конфигурации регистратора требует перечисления различных объектов для создания и связей между ними. Например, можно создать обработчик с именем console и затем сказать, что регистратор с именем startup будет отправлять свои сообщения обработчику console. Эти объекты не ограничиваются теми, которые предоставляются модулем logging, потому что можно написать свой собственный класс Formatter или Handler. Параметры этих классов также могут включать внешние объекты, такие как sys.stderr. Синтаксис для описания этих объектов и соединений определяется в разделе "Соединения объектов".

Так же смотрите пример конфигурации регистратора из словаря.

Словарь должен содержать следующие ключи:

  • Ключ version - целое число, представляющего версию схемы. Единственное допустимое значение в настоящее время - 1, но наличие этого ключа позволяет схеме развиваться, сохраняя при этом обратную совместимость.

Все остальные ключи являются необязательными, но если они присутствуют, они будут интерпретированы, как описано ниже. Во всех нижеприведенных случаях, когда упоминается configuring dict, будет проверяться наличие специального ключа '()', чтобы определить, требуется ли пользовательская реализация. Если это так, механизм, описанный в пользовательских объектах ниже, используется для создания экземпляра. В противном случае контекст используется для определения того, что нужно создавать.

  • Ключ formatters - соответствующее значение будет словарем dict, в котором каждый ключ является идентификатором Formatter, а каждое значение - словарем, описывающим, как настроить соответствующий объект Formatter.

    В конфигурации словаря dict для настройки ищутся ключи формата format и datefmt (по умолчанию None), которые используются для создания экземпляра Formatter.

    Например:

    'formatters': { 
            # идентификатор форматера "standard"
            'standard': { 
                # конфигурация для форматера с идентификатором "standard" 
                'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
            },
        }
    

    Изменено в Python 3.8: для проверки формата, в словарь конфигурации, в раздел formatters может быть добавлен ключ validate (по умолчанию True).

  • Ключ filters - соответствующее значение будет словарем dict, в которой каждый ключ является идентификатором Filter, а каждое значение - словарем, описывающей, как настроить соответствующий объект Filter.

    В конфигурации словаря dict для настройки ищется ключ c именем name (по умолчанию это пустая строка), которое используется для создания экземпляра Filter.

  • Ключ handlers - соответствующее значение будет словарем dict, в которой каждый ключ является идентификатором Handler, а каждое значение - словарем, описывающей, как настроить соответствующий объект Handler.

    В конфигурации словаря dict для настройки ищутся ключи:

    • class (обязательно). Полное имя класса обработчика.
    • level (необязательно). Уровень логирования обработчика.
    • formatter (необязательно). Идентификатор форматера для этого обработчика.
    • filters (необязательно). Список идентификаторов фильтров для этого обработчика.

    Все остальные ключи передаются в качестве ключевых аргументов в конструктор обработчика. Например, учитывая фрагмент:

    handlers:
        console:
            class : logging.StreamHandler
            formatter: brief
            level   : INFO
            filters: [allow_foo]
            stream  : ext://sys.stdout
        file:
            class : logging.handlers.RotatingFileHandler
            formatter: precise
            filename: logconfig.log
            maxBytes: 1024
            backupCount: 3
    

    Обработчик с идентификатором console создается как logging.StreamHandler, используя sys.stdout в качестве основного потока. Обработчик c идентификатором file создается как logging.handlers.RotatingFileHandler и с ключевыми аргументами filename='logconfig.log', maxBytes=1024, backupCount=3.

  • Ключ loggers - соответствующее значение будет словарем dict, в которой каждый ключ является именем Logger, а каждое значение - словарем, описывающим, как настроить соответствующий объект Logger.

    В конфигурации словаря dict для настройки ищутся ключи:

    • level (необязательно). Уровень логирования регистратора.
    • propagate (необязательно). Настройка распространения регистратора.
    • filters (необязательно). Список идентификаторов фильтров для этого регистратора.
    • handlers (необязательно). Список идентификаторов обработчиков для этого регистратора.

    Указанные регистраторы будут настроены в соответствии с указанным уровнем level, распространением propagate, фильтрами filters и обработчиками handlers.

  • Ключ root - это будет конфигурация для корневого регистратора Logger. Обработка конфигурации будет такой же, как для любого регистратора, за исключением того, что параметр распространения propagate не будет учитаваться.

  • Ключ Incremental - следует ли интерпретировать конфигурацию как инкрементную к существующей конфигурации. Значение Incremental по умолчанию равно False, что означает, что указанная конфигурация заменяет существующую конфигурацию той же семантикой, которая используется существующим API fileConfig().

    Если Incremental задано значение True , конфигурация обрабатывается, как описано в разделе "Инкрементная конфигурация".

  • Ключ disable_existing_loggers - нужно ли отключать какие-либо существующие некорневые регистраторы. Этот параметр отражает параметр с тем же именем в fileConfig(). Если этот ключ не указан, то по умолчанию он будет равен True. Это значение игнорируется, если ключ incremental имеет значение True.

Инкрементная конфигурация.

Детализацией регистраторов Logger и обработчиков Handler можно управлять установкой уровней логирования, а в случае регистраторов, еще а флагов распространения propagate.

Таким образом, когда ключ Incremental в словаре-конфигурации присутствует и имеет значение True, то система будет полностью игнорировать любые ключи formatters и filters и обрабатывает только настройки ключей level в записях handlers, а также настройки ключей level и propagate в записях loggers и root записях.

Соединения объектов.

Примечание: здесь используется YAML, потому что он немного более читабелен, чем эквивалентная исходная форма Python для словаря.

Схема описывает набор объектов журналирования - регистраторов, обработчиков, форматеров, фильтров - которые связаны друг с другом в графе объектов. Таким образом, схема должна представлять связи между объектами. Например, скажем, что после настройки определенный регистратор прикрепил к нему определенный обработчик. Для целей этого обсуждения мы можем сказать, что регистратор представляет источник, а обработчик - назначение соединения между ними. Конечно, в сконфигурированных объектах это представлено регистратором, содержащим ссылку на обработчик. В настройке конфигурации это делается путем присвоения каждому целевому объекту идентификатора, который однозначно его идентифицирует, а затем с помощью идентификатора в конфигурации исходного объекта, чтобы указать, что существует соединение между исходным и целевым объектом с этим идентификатором.

Так, например, рассмотрим следующий фрагмент YAML:

formatters:
  brief:
    # конфигурация для форматера с идентификатором "brief" 
  precise:
    # конфигурация для форматера с идентификатором "precise"
handlers:
  h1: #Это идентификатор обработчика
   # конфигурация обработчика с идентификатором "h1"
   formatter: brief
  h2: #Еще один идентификатор
   # конфигурация обработчика с идентификатором "h2"
   formatter: precise
loggers:
  foo.bar.baz:
    # Другая конфигурация для логгера "foo.bar.baz"
    handlers: [h1, h2]

Идентификаторы для регистраторов - это имена регистраторов, которые будут использоваться программно для получения ссылки на эти регистраторы, например foo.bar.baz. Идентификаторы для Formatters и Filters могут быть любыми строковыми значениями (например brief, precise, указанными выше), и они являются временными, поскольку они имеют смысл только для обработки словаря конфигурации и используются для определения соединений между объектами, и не сохраняются нигде, когда вызов конфигурации завершен.

Вышеприведенный фрагмент указывает, что к регистратору с именем foo.bar.baz должны быть прикреплены два обработчика, которые описываются идентификаторами обработчиков h1 и h2. Formatter для h1 - это тот, который описан с помощью идентификатора brief, а Formatter для h2 - это тот, который описан с идентификатором precise.

Пользовательские объекты.

Примечание: здесь используется YAML, потому что он немного более читабелен, чем эквивалентная исходная форма Python для словаря.

Схема поддерживает пользовательские объекты для обработчиков, фильтров и форматеров. Регистраторам не нужно иметь разные типы для разных экземпляров, поэтому в этой схеме конфигурации нет поддержки пользовательских классов регистраторов.

Настраиваемые объекты описываются словарями, в которых подробно описывается их конфигурация. В некоторых местах система ведения журналов сможет из контекста определить, как должен создаваться объект, но когда создается экземпляр пользовательского объекта, система не будет знать, как это сделать. Чтобы обеспечить полную гибкость для создания пользовательских объектов, пользователю необходимо предоставить "фабрику" - вызываемый объект, который вызывается из словаря конфигурации и который возвращает экземпляр объекта. На это указывает абсолютный путь импорта на фабрику, доступный по специальному ключу '()'.

Фрагмент YAML c конкретным примером:

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 с указанной строкой формата format. Второй, с идентификатором default, имеет более длинный формат, а также явно определяет формат времени и приведет к инициализации logging.Formatter с этими двумя строками формата. Показанные в исходной форме Python, краткие и стандартные форматы имеют под-словари конфигурации:

{
  '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
}

и он содержит специальный ключ '()', который означает, что требуется пользовательская реализация. В этом случае будет использоваться указанный фабричный вызов. Если это фактический вызываемый объект, то он будет использоваться напрямую - в противном случае, если указать строку (как в примере), этот вызываемый объект будет найден с использованием обычных механизмов импорта. Он будет вызываться с остальными элементами в под-словаре конфигурации в качестве ключевого аргумента. В приведенном выше примере Formatter с идентификатором custom будет возвращен вызовом:

my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)

Ключ '()' использовался в качестве специального ключа, поскольку он не является допустимым ключевым аргументом и поэтому не будет конфликтовать с их именами.

Пример конфигурации регистратора из словаря.

LOGGING_CONFIG = { 
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': { 
        'standard': { 
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': { 
        'default': { 
            'level': 'INFO',
            'formatter': 'standard',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',  # Default is stderr
        },
    },
    'loggers': { 
        '': {  # root logger
            'handlers': ['default'],
            'level': 'WARNING',
            'propagate': False
        },
        'my.packg': { 
            'handlers': ['default'],
            'level': 'INFO',
            'propagate': False
        },
        '__main__': {  # if __name__ == '__main__'
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': False
        },
    } 
}

Использование.

Необходимо обязательно запустить эту конфигурацию при помощи logging.config.dictConfig(LOGGING_CONFIG) перед импортом сторонних модулей/пакетов, дабы исключить ведение журналов для этих сторонних модулей/пакетов.

# Вызываем один раз при запуске:
logging.config.dictConfig(LOGGING_CONFIG)
# Включить в каждый модуль:
log = logging.getLogger(__name__)
log.debug("Ведение журнала настроено.")