ПрограммированиеPython backend разработчик

Как устроено логирование в Python через модуль logging? Какие уровни логирования существуют и как правильно настраивать логгер в многомодульном проекте? Приведите примеры, разъясните тонкости и распространенные ошибки.

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Модуль logging — стандартный инструмент Python для ведения логов. Он реализует иерархию логгеров и поддерживает уровни логирования (severity levels): DEBUG, INFO, WARNING, ERROR, CRITICAL. Правильное использование позволяет централизованно управлять выводом, сохранять логи в файлы, отправлять их по email, фильтровать по уровню и т.д.

Главная идея — создавать логгеры с именами (logging.getLogger(__name__)) в каждом модуле, не создавать глобальный root-логгер с нуля в каждом месте. Конфигурирование (формат, обработчики, уровень) делается централизованно на старте приложения.

Пример настройки:

import logging logging.basicConfig(format='%(levelname)s:%(name)s:%(message)s', level=logging.INFO) logger = logging.getLogger(__name__) def foo(): logger.info('Информационное сообщение') logger.error('Ошибка!') foo()

Вопрос с подвохом.

Почему нельзя вызывать logging.basicConfig() в каждом модуле? Что произойдет, если сделать это?

Ответ: logging.basicConfig() настраивает root-логгер только один раз за сессию Python. Повторные вызовы, если root-логгер уже был инициализирован, будут проигнорированы. В результате, если разные модули пытаются вызвать basicConfig() со своими форматами/уровнями — сработает только самый первый!

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В большом проекте каждый разработчик настраивал logging на свой вкус через basicConfig и локальные обработчики. Из-за этого некоторые логи не выводились вовсе, другие дублировались 10-кратно, а сообщения разных модулей не влезали в один файл.


История

При миграции веб-сервиса на многоуровневое логирование забыли указывать имя логгера через getLogger(__name__), везде писали в root-логгер. В итоге невозможно было определить, откуда пришел конкретный лог.


История

Использовали функцию logger.error() для записи всех сообщений, даже неошибочных. В результате, автоматические системы мониторинга постоянно "поднимали тревогу", потому что видели высокий уровень ошибок, хотя это были просто debug/информационные сообщения.