Как временно изменить формат регистрируемых сообщений в Python? - PullRequest
13 голосов
/ 27 июля 2011

Какой самый простой метод для временного изменения формата сообщения регистрации в Python (через модуль регистрации)?

Цель состоит в том, чтобы иметь некоторый стандартный формат сообщения, в то время как возможность временно добавлять информацию о некоторыхчитаемый файл (как его имя);формат сообщения должен вернуться к значению по умолчанию, когда файл больше не читается.Программа, которая генерирует сообщения, не знает о том, какой файл читается, поэтому было бы неплохо, если бы в ее сообщении автоматически содержалось соответствующее имя файла (сообщение об ошибке будет выглядеть так:файл ***:… "вместо« ОШИБКА:… »).

Ответы [ 3 ]

10 голосов
/ 31 июля 2011

Вот простое решение, которое может быть выведено из Vinay Sajip 's * HOWTO ; он в основном обновляет форматировщик логов с setFormatter():

import logging

logger = logging.getLogger()  # Logger
logger_handler = logging.StreamHandler()  # Handler for the logger
logger.addHandler(logger_handler)

# First, generic formatter:
logger_handler.setFormatter(logging.Formatter('%(message)s'))
logger.error('error message')  # Test

# New formatter for the handler:
logger_handler.setFormatter(logging.Formatter('PROCESSING FILE xxx - %(message)s'))
logger.error('error message')  # Test

Это правильно выдает:

error message
PROCESSING FILE xxx - error message

(где xxx может быть динамически установлен для обрабатываемого файла, как указано в вопросе).

8 голосов
/ 27 июля 2011

Есть несколько способов.Помимо уже задокументированных (extra аргумент для регистрации вызовов, LoggerAdapter, Filter), другим способом было бы указать пользовательский класс форматирования, экземпляр которого вы можете держать в курсе о файлев процессе.Например:

class FileProcessingFormatter(logging.Formatter):
    def __init__(self, fmt, datefmt=None, current_file=None):
        super(FileProcessingFormatter, self).__init__(fmt, datefmt)
        self.orig_fmt = fmt
        self.current_file = current_file

    def format(self, record):
        if self.current_file is None:
            self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', '')
        else:
            self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__',
                            ' while processing %r' % self.current_file)
        return super(FileProcessingFormatter, self).format(record)

Создание экземпляра средства форматирования ...

f = FileProcessingFormatter('%(levelname)s__FILE_PLACEHOLDER__ %(message)s')
for h in relevant_handlers:
    h.setFormatter(f)

Обработка файлов ...

f.current_file = fn
process_file(fn)
f.current_file = None

Это очень упрощенно - например, недля использования в многопоточных средах, если обработка файла выполняется разными потоками одновременно.

Обновление: Хотя обработчики корневого регистратора доступны через logging.getLogger().handlers, это деталь реализации, которая может измениться.Поскольку ваши требования не так просты, возможно, вы могли бы использовать dictConfig() для настройки ведения журналов (доступно через проект logutils для более старых версий Python).

0 голосов
/ 03 мая 2019

Я не рекомендую это;но вы можете сказать, что первый обработчик рутов - тот, который облажался, и измените его напрямую

import logging
ROOT_LOGGER = logging.getLogger()
ROOT_LOGGER.handlers[0].setFormatter(logging.Formatter(
    '%(asctime)s:%(levelname)s:%(name)s:%(message)s\n'
))

, если вы находитесь в любой системе с управляемым ведением журнала;это, вероятно, собирается застрелить вашу ногу;действительно было бы лучше иметь возможность определить точную ссылку на обработчик, который вы хотите изменить, и изменить его;

, но никого не волнует, насколько он сломан, если он работает правильно? / s

...