Управление выводом сообщений логгера в Python: ошибки
Быстрый ответ
Для того чтобы пресечь вывод логов Python в stderr
, используйте NullHandler
:
import logging
logging.getLogger().addHandler(logging.NullHandler())
Либо, если хотите полностью отключить stderr
, перенаправьте его в файл или в os.devnull
:
import logging, os
logging.basicConfig(handlers=[logging.StreamHandler(open(os.devnull, 'w'))])
С NullHandler
вы будете полностью игнорировать логи. А перенаправление в os.devnull
позволит избавиться от лишних сообщений.
Останавливаем распространение: управляем распространением сообщений от логгера
Понимаем механизм распространения сообщений от логгера
Для настройки передачи сообщений от логгера к его "родителям", следует разобраться с атрибутом logger.propagate
:
logger = logging.getLogger('my_logger')
logger.propagate = False
Отключение propagate
предотвратит вывод логов на уровне корневого логгера и, соответственно, в stderr
.
Берём под контроль отдельные обработчики
Для детальной настройки логирования стоит отключать обработчики по отдельности:
for handler in logger.handlers:
if isinstance(handler, logging.StreamHandler):
logger.removeHandler(handler)
Таким образом, вы сохраните работу других важных обработчиков, например тех, которые записывают данные в файл.
Единая команда для управления всем: продвинутое и временное управление логгером
Осваиваем способ работы с менеджерами контекста
Для временного контроля над процессом логирования можно использовать менеджер контекста:
import contextlib
@contextlib.contextmanager
def pause_logging(logger):
original_handlers = logger.handlers
logger.handlers = [logging.NullHandler()]
try:
yield
finally:
logger.handlers = original_handlers
with pause_logging(logging.getLogger()):
# Логирование временно отключено
Как не допустить автоматическое восстановление стандартного обработчика
Следите за тем, чтобы логгер не возвращал стандартные обработчики, когда они у него отсутствуют.
Приводим уровень "шума" в порядок: настраиваем уровни логирования
Комфортная настройка уровней
Можно настроить уровни логирования, задавая их для каждого обработчика в отдельности:
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARN)
logger.addHandler(console_handler)
После этого будут проходить только предупреждения с уровнем WARNING и выше.
Отключаем логирование глобально
Чтобы полностью выключить логирование:
logging.disable(logging.CRITICAL)
Если в будущем потребуется вернуть логирование, его можно активировать, установив уровень на logging.NOTSET
:
logging.disable(logging.NOTSET)
Визуализация
Приведем наглядное сравнение кода до и после отключения стандартного потока ошибок stderr:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug("Это попадёт в stderr")
logging.getLogger().handlers[0].stream = None
logging.debug("Это НЕ попадёт в stderr")
Результат:
До: [📢, 📚(Ваш код)]
После: [🔕, 📚(Ваш код)]
Отключив логирование, вы, таким образом, замените "шум" на тишину.
Держим всё под контролем: надёжная защита настроек логирования
Безопасное взаимодействие со стандартными обработчиками
Перед тем как вносить изменения, всегда проверяйте существование стандартного обработчика:
if logger.handlers:
logger.handlers[0].stream = None
Сначала файловые обработчики, затем stdout
Файловые обработчики следует добавлять перед тем, как настроить стандартный поток вывода:
file_handler = logging.FileHandler('logfile.log')
logger.addHandler(file_handler)
Обеспечиваем надёжность вашего менеджера контекста с помощью обработки исключений
Укрепите ваш менеджер контекста, обеспечив обработку возможных исключений:
@contextlib.contextmanager
def bulletproof_pause_logging(logger):
original_handlers = logger.handlers
logger.handlers = [logging.NullHandler()]
try:
yield
finally:
try:
logger.handlers = original_handlers
except Exception as e:
logger.error("Возникла ошибка при попытке восстановить обработчики логгера.", exc_info=e)
Таким образом, ваш менеджер контекста продолжит работу даже при возникновении непредвиденных обстоятельств.
Полезные материалы
- Logging HOWTO — Документация Python 3.12.2 — Официальное руководство по работе с модулем логирования Python.
- Logging in Python – Real Python — Подробное руководство по модулю логирования в Python.
- logging — Ведение журнала событий для Python — Документация Python 3.12.2 — Глубокое изучение всех возможностей модуля
logging
. - Logging Cookbook — Документация Python 3.12.2 — Практические рекомендации для работы с с модулем логирования.
- Logging HOWTO — Управление обработчиками – Документация Python — Руководство по управлению обработчиками потока
stderr
.