Logging - важная часть разработки и поддержки программного обеспечения. В Python встроенный модуль logging предоставляет гибкий и мощный инструментарий для ведения журналов. Давайте углубимся в детали этого модуля и рассмотрим его основные компоненты и продвинутые функции.
1. Основы logging
Прежде всего, для использования logging необходимо импортировать соответствующий модуль:
import logging
Базовое использование logging очень просто:
logging.debug('Это сообщение уровня DEBUG')
logging.info('Это информационное сообщение')
logging.warning('Это предупреждение')
logging.error('Это сообщение об ошибке')
logging.critical('Это критическое сообщение')
По умолчанию, только сообщения уровня WARNING и выше будут выводиться на консоль.
2. Конфигурация logging
Для более тонкой настройки logging можно использовать функцию basicConfig():
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', filename='app.log', filemode='w')
Эта конфигурация устанавливает уровень логирования DEBUG, задает формат сообщений, указывает файл для записи логов и режим записи (перезапись).
3. Форматирование сообщений
Форматирование сообщений - важный аспект logging. Вы можете использовать различные атрибуты в строке формата:
- %(asctime)s: Время создания записи
- %(name)s: Имя логгера
- %(levelname)s: Текстовое представление уровня логирования
- %(message)s: Сообщение лога
- %(filename)s: Имя файла, из которого была вызвана функция логирования
- %(funcName)s: Имя функции, в которой произошло логирование
- %(lineno)d: Номер строки, где произошло логирование
Пример более сложного форматирования:
format_str = '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
logging.basicConfig(format=format_str)
4. Использование getLogger()
Функция getLogger() позволяет создавать именованные логгеры, что особенно полезно в больших приложениях:
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# Создание обработчика
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
# Создание форматтера
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# Добавление обработчика к логгеру
logger.addHandler(handler)
logger.debug('Это отладочное сообщение')
5. Обработчики (Handlers)
Обработчики определяют, куда будут отправляться сообщения лога. Python предоставляет несколько типов обработчиков:
- StreamHandler: Отправляет сообщения в потоки (например, sys.stdout, sys.stderr)
- FileHandler: Отправляет сообщения в файл
- RotatingFileHandler: Отправляет сообщения в файл с возможностью ротации по размеру
- TimedRotatingFileHandler: Отправляет сообщения в файл с возможностью ротации по времени
Пример использования
RotatingFileHandler:
from logging.handlers import RotatingFileHandler
logger = logging.getLogger('my_app')
handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3)
logger.addHandler(handler)
6. Фильтры (Filters)
Фильтры позволяют более точно контролировать, какие сообщения логируются:
class MyFilter(logging.Filter):
def filter(self, record):
return 'important' in record.getMessage()
logger = logging.getLogger('my_app')
logger.addFilter(MyFilter())
7. Логирование исключений
Для логирования исключений можно использовать метод exception():
try:
1 / 0
except ZeroDivisionError:
logging.exception("Произошло деление на ноль")
Этот метод автоматически добавляет информацию о стеке вызовов к сообщению лога.
8. Конфигурация из файла
Для больших приложений удобно хранить конфигурацию logging в отдельном файле:
import logging.config
logging.config.fileConfig('logging.conf')
logger = logging.getLogger('my_app')
Использование dictConfig Альтернативой fileConfig является dictConfig, которая позволяет настраивать logging с помощью словаря Python:
import logging.config
logging_config = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
},
'handlers': {
'default': {
'level': 'INFO',
'formatter': 'standard',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
},
},
'loggers': {
'': {
'handlers': ['default'],
'level': 'INFO',
'propagate': True
}
}
}
logging.config.dictConfig(logging_config)
logger = logging.getLogger(__name__)
10. Логирование в многопоточных приложениях
Модуль logging потокобезопасен, но при работе с несколькими потоками следует быть осторожным:
import logging
import threading
def worker(arg):
logger = logging.getLogger('myapp.worker')
logger.info('Worker running with argument %s', arg)
logging.basicConfig(level=logging.INFO, format='%(threadName)s: %(message)s')
threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
11. Создание пользовательских уровней логирования
Вы можете создавать собственные уровни логирования:
VERBOSE = 15
logging.addLevelName(VERBOSE, "VERBOSE")
def verbose(self, message, *args, **kwargs):
if self.isEnabledFor(VERBOSE):
self._log(VERBOSE, message, args, **kwargs)
logging.Logger.verbose = verbose
logger = logging.getLogger(__name__)
logger.setLevel(VERBOSE)
logger.verbose("Это сообщение уровня VERBOSE")
12. Контекстные менеджеры для временного изменения уровня логирования
Иногда требуется временно изменить уровень логирования:
import contextlib
@contextlib.contextmanager
def temporary_log_level(logger, level):
old_level = logger.level
logger.setLevel(level)
try:
yield
finally:
logger.setLevel(old_level)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
with temporary_log_level(logger, logging.DEBUG):
logger.debug("Это сообщение будет залогировано")
logger.debug("А это сообщение не будет залогировано")
Заключение
Модуль logging в Python предоставляет мощные инструменты для ведения журналов в приложениях. От базового использования до продвинутых техник, таких как пользовательские форматтеры, обработчики и фильтры, logging позволяет гибко настраивать систему журналирования под конкретные нужды проекта. Правильное использование logging может значительно упростить отладку и мониторинг приложений, особенно в продакшн-среде.
Спасибо за прочтение статьи! Надеюсь она окажется вам полезной! Оставляйте комментарии и подписывайтесь! Всем печенек)