Python logger всегда выводит отладочные сообщения независимо от фильтра - PullRequest
0 голосов
/ 12 июня 2019

В настоящее время я создаю подкласс logging.Logger, в котором есть фильтр, основанный на уровне, и этот уровень может меняться между журналами вызовов (поэтому я делаю это с фильтром, а не setLevel()).,Однако, похоже, что мой регистратор всегда печатает сообщения с уровнем DEBUG, независимо от фильтра.Вот мой код ниже

import logging


class _LevelFilter(logging.Filter):

    def filter(self, record):
        SimpleLogger.setLevel(_DEFAULT_LEVEL)
        return 1 if SimpleLogger.isEnabledFor(record.levelno) else 0


class _SimpleLogger(logging.getLoggerClass()):
    def __init__(self, name=None, level=logging.DEBUG):
        super().__init__(name, level)
        self.setLevel(logging.DEBUG)
        _handler = logging.StreamHandler()
        _handler.setLevel(logging.DEBUG)
        self.addHandler(_handler)
        self.addFilter(_LevelFilter())


_DEFAULT_LEVEL = 'WARNING'
SimpleLogger = _SimpleLogger()

if __name__ == '__main__':
    SimpleLogger.debug('testing debug')
    SimpleLogger.info('testing info')
    SimpleLogger.warning('testing warning')
    SimpleLogger.critical('testing critical')
    SimpleLogger.debug('testing debug')

Код выше дает следующий вывод:

testing debug
testing warning
testing critical
testing debug

Я знаю, что если я объявлю SimpleLogger как отдельную переменную вместо подкласса, это будет работать, но мне нужно использовать подкласс по разным причинам.Для справки, вот версия, не использующая работающий подкласс.

SimpleLogger = logging.getLogger()
SimpleLogger.setLevel(logging.DEBUG)

_handler = logging.StreamHandler()
_handler.setLevel(logging.DEBUG)
SimpleLogger.addHandler(_handler)
SimpleLogger.addFilter(_LevelFilter())

_DEFAULT_LEVEL = 'WARNING'

Я не могу понять, почему сообщения отладки всегда печатаются.Различия между версиями подкласса и не подкласса не очень велики, и установка уровня должна привести к тому, что отладочные и информационные сообщения не будут появляться.Любая помощь будет оценена, спасибо!

1 Ответ

2 голосов
/ 12 июня 2019

Я наконец нашел решение!Таким образом, оказывается, что Python 3.7 вводит кеш в логгер, который кеширует результаты из isEnabledFor ().Поскольку фильтр запускается после начальной проверки isEnabledFor (), старый результат все еще кэшируется, что приводит к этому странному поведению.Решение состоит в том, чтобы не использовать фильтр таким образом.Вместо этого я действительно хотел альтернативный способ получить эффективный уровень регистратора. Вот код для фиксированного регистратора:

Редактировать: Оказывается, что мое оригинальное решение все еще не работает, и проблема с кешем все еще существует.Похоже, это относится к регистраторам, которые подкласс от logging.getLoggerClass (), поэтому вам необходимо каждый раз очищать кэш.Новое решение ниже.(Кроме того, я сильно упростил, чтобы включить только необходимые вещи.)

class _SimpleLogger(logging.getLoggerClass()):
    def __init__(self, name=None, level=logging.DEBUG):
        super().__init__(name, level)
        _handler = logging.StreamHandler()
        self.addHandler(_handler)

    def isEnabledFor(self, level):
        # Clears logging cache introduced in Python 3.7.
        # Clear here since this is called by all logging methods that write.
        self._cache = {}  # Set instead of calling clear() for compatibility with Python <3.7
        return super().isEnabledFor(level)

# Confirm that this works
if __name__ == "__main__":
    logger = SimpleLogger()
    logger.setLevel(logging.DEBUG)
    # Next 4 logs should print
    logger.debug('d')
    logger.info('i')
    logger.warning('w')
    logger.error('e')

    # Only warning and error logs should print
    logger.setLevel(logging.WARNING)
    logger.debug('d')
    logger.info('i')
    logger.warning('w')
    logger.error('e')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...