- PVSM.RU - https://www.pvsm.ru -
Если вы пишете на Python, скорее всего, ваша карьера разработчика начиналась с одной простой, но незаменимой команды — print(). Нужно проверить значение переменной? print(my_variable). Хотите убедиться, что функция вообще вызвалась? print("Я внутри функции!"). Этот метод прост, интуитивно понятен и кажется верным другом в мире отладки.
Но дружба эта длится ровно до первого серьезного проекта. Внезапно оказывается, что ваш терминал завален десятками отладочных сообщений, и вы уже не понимаете, какое из них к чему относится. Вы начинаете писать print("--- HERE ---"), чтобы хоть как-то ориентироваться в этом хаосе. А когда приходит время выкатывать код в продакшен, вы судорожно ищете и комментируете все свои print(), надеясь не пропустить ни одного.
В этот момент опытные коллеги (или статьи в интернете) говорят вам: "Для этого есть стандартный модуль logging!". И они правы. logging — это мощный, гибкий и правильный инструмент. Но давайте будем честны, его настройка часто напоминает бюрократическую процедуру. Чтобы просто начать писать логи в файл с указанием времени и уровня, нужно написать что-то вроде этого:
import logging
# Настройка... снова и снова
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("debug.log"),
logging.StreamHandler()
]
)
logging.info("Пользователь вошел в систему.")
logging.warning("Не удалось найти файл конфигурации.")
Это работает, но это громоздко. Пять-шесть строк кода только для того, чтобы начать. А если вам понадобится ротация файлов, кастомные форматы или что-то посложнее? Конфигурация становится еще запутаннее.
Именно в этот момент на сцену выходит Loguru. Эта библиотека была создана для того, чтобы избавить нас от страданий. Она берет лучшее из двух миров: феноменальную простоту print() и всю мощь взрослого логирования, но без лишнего "шума" и сложной настройки.
Что, если я скажу вам, что цветное логирование в консоль, запись в файл с автоматической ротацией и сжатием, а также невероятно удобная отладка исключений могут быть настроены всего одной строкой кода?
В этой статье мы раз и навсегда забудем про print() для отладки и посмотрим, как Loguru может сделать ваше логирование не только мощным, но и по-настоящему красивым и удобным.
Итак, мы оставили позади боль от print() и сложность logging. Давайте посмотрим, что предлагает Loguru и почему его называют "логированием для удовольствия".
Как и положено современному Python-пакету, установка предельно проста и выполняется одной командой в терминале:
pip install loguru
Всё, библиотека готова к работе. Никаких зависимостей, никаких сложных настроек окружения.
Помните, сколько кода нужно было для базовой настройки logging? Забудьте. С Loguru вы просто импортируете готовый к использованию объект logger и начинаете его использовать.
from loguru import logger
logger.info("Hello, Loguru!")
logger.warning("Это предупреждение, будьте внимательны.")
logger.debug("Это сообщение не будет видно по умолчанию.")
Запустите этот код, и вы увидите в консоли что-то вроде этого:
2025-11-13 13:00:00.000 | INFO | __main__:__main__:3 - Hello, Loguru!
2025-11-13 13:00:00.000 | WARNING | __main__:__main__:4 - Это предупреждение, будьте внимательны.
Обратите внимание: debug-сообщение не появилось. По умолчанию Loguru, как и любая серьезная система логирования, показывает сообщения уровня INFO и выше. Это правильное поведение, которое избавляет от лишнего шума в консоли.
Давайте внимательно посмотрим на первую строку вывода:
2025-11-13 13:00:00.000 | INFO | __main__:__main__:3 - Hello, Loguru!
Даже без единой строчки конфигурации Loguru сразу предоставляет нам богатый контекст:
Дата и время: 2025-11-13 13:00:00.000 — точная временная метка, когда произошло событие. Больше не нужно гадать, к какому моменту времени относится print.
Уровень лога: INFO — показывает важность сообщения. WARNING говорит о потенциальной проблеме, ERROR — о серьезной ошибке.
Местоположение: __main__:__main__:3 — это самая полезная часть. Loguru автоматически указывает имя файла, функцию и номер строки, откуда был сделан вызов. Это невероятно ускоряет отладку!
Сообщение: Hello, Loguru! — непосредственно то, что мы хотели записать.
Если вы запустите приведенный выше код в терминале, который поддерживает цвета (а сегодня это делают почти все), вы увидите еще одну приятную особенность: вывод будет раскрашен!
INFO обычным белым.
WARNING — заметным желтым.
ERROR и CRITICAL — тревожно-красным.
Это не просто украшение. Цвета помогают мгновенно сканировать лог глазами и находить проблемы, не вчитываясь в каждое слово. Это та самая "красота" и "удобство", которых так не хватает стандартным инструментам.
Всего один import — и мы уже получили цветное, информативное и правильно структурированное логирование. Это и есть магия Loguru "из коробки". А ведь мы еще даже не начали знакомиться с его основными возможностями
Мы убедились, что Loguru прекрасен "из коробки". Но его настоящая сила раскрывается, когда мы начинаем использовать его основные функции. И здесь Loguru остается верен своему принципу: максимум пользы при минимуме кода.
Как мы уже видели, Loguru поддерживает стандартные уровни важности сообщений:
TRACE (самый подробный)
DEBUG
INFO
SUCCESS (приятное дополнение для успешных операций)
WARNING
ERROR
CRITICAL
По умолчанию в консоль выводятся сообщения от INFO и выше. Это легко изменить. Например, чтобы включить DEBUG-сообщения, нужно перенастроить стандартный обработчик (sink), указав новый уровень:
from loguru import logger
# Удаляем стандартный обработчик и добавляем новый с уровнем DEBUG
logger.remove()
logger.add(sys.stderr, level="DEBUG") # sys.stderr - это стандартный поток ошибок (консоль)
logger.debug("Теперь это сообщение будет видно!")
logger.info("И это, конечно, тоже.")
Это одна из самых мощных и востребованных функций. Забудьте про FileHandler и его сложную настройку. С Loguru все делается одной командой — logger.add().
Просто записать в файл:
from loguru import logger
logger.add("my_app.log")
logger.info("Это сообщение попадет и в консоль, и в файл my_app.log")
Но настоящая магия начинается, когда мы добавляем параметры в эту команду.
Автоматическая ротация файлов (Rotation)
Ваш лог-файл не будет расти бесконечно, занимая все место на диске. Loguru может автоматически создавать новый файл, когда старый достигает определенного размера или проходит определенное время.
# Создавать новый файл, как только текущий достигнет 500 MB
logger.add("big_file.log", rotation="500 MB")
# Создавать новый файл каждую неделю
logger.add("weekly_log.log", rotation="1 week")
# Создавать новый файл каждый день в полночь
logger.add("daily_log.log", rotation="00:00")
Автоматическая очистка старых логов (Retention)
Чтобы старые логи не копились вечно, можно указать, как долго их хранить.
# Хранить логи за последние 10 дней
logger.add("cleaned_log.log", retention="10 days")
Автоматическое сжатие (Compression)
Loguru может даже самостоятельно архивировать старые лог-файлы, чтобы они занимали меньше места.
# При ротации сжимать старые файлы в zip-архив
logger.add("compressed_log.log", rotation="10 MB", compression="zip")
Давайте соберем все вместе в один мощный пример для реального проекта:
from loguru import logger
# Настраиваем логирование для продакшена:
# - Пишем в файл `prod.log`
# - Уровень - INFO и выше
# - Ротация при достижении 10 MB
# - Храним файлы 1 месяц
# - Сжимаем старые логи в .gz
logger.add("prod.log", level="INFO", rotation="10 MB", retention="1 month", compression="gz")
logger.info("Система запущена и готова к работе!")
Всего одна строка кода заменяет десятки строк конфигурации стандартного logging. Это невероятно удобно.
Еще одна мелочь, которая делает жизнь разработчика проще. Loguru использует для форматирования строк фигурные скобки, как в f-strings, что гораздо читабельнее и привычнее, чем старый %-стиль.
user_id = 123
status = "success"
# Привычный и читаемый синтаксис
logger.info("Аутентификация для пользователя {id} прошла со статусом: {status}", id=user_id, status=status)
Вывод будет таким:
... | INFO | ... - Аутентификация для пользователя 123 прошла со статусом: success
Мы рассмотрели базовые, но самые часто используемые возможности Loguru. Уже на этом этапе видно, насколько он упрощает и ускоряет разработку. Но это еще не все — в следующей части мы погрузимся в продвинутые техники, которые сделают вашу отладку по-настоящему волшебной.
Мы освоили основы, которые уже делают работу с логами приятнее. Но Loguru был создан не только для удобства — он предоставляет мощнейшие инструменты для отладки, которые могут сэкономить вам часы поиска ошибок. Давайте рассмотрим функции, которые отличают новичка от профессионала.
Это, пожалуй, главная "киллер-фича" Loguru. Стандартный трейсбэк в Python информативен, но часто хочется видеть значения переменных, которые привели к ошибке.
Логирование внутри try...except
Во-первых, вы можете использовать logger.exception(), который автоматически захватит и красиво отформатирует информацию о последнем исключении.
from loguru import logger
try:
result = 10 / 0
except ZeroDivisionError:
logger.exception("Произошла ошибка при вычислении.")
Вывод будет содержать не только ваше сообщение, но и полный, аккуратно отформатированный трейсбэк ошибки.
Декоратор @logger.catch — ваша секретная кнопка "Найти ошибку"
Но настоящий прорыв — это декоратор @logger.catch. Вы можете просто "обернуть" в него любую функцию, и Loguru автоматически поймает любое исключение, которое в ней произойдет, и выведет самый подробный отчет из возможных.
Посмотрите на этот пример:
from loguru import logger
@logger.catch
def calculate(a, b, c):
return a / b + c
calculate(10, 0, 5) # Эта строка вызовет ошибку
Без @logger.catch вы бы получили стандартный трейсбэк. Но с декоратором Loguru выведет в консоль нечто гораздо более ценное:
> 2025-11-13 13:00:00.000 | ERROR | __main__:calculate:5 - An error has been caught in function 'calculate', process 'MainProcess' (1234), thread 'MainThread' (5678):
Traceback (most recent call last):
...
File "my_script.py", line 6, in <module>
calculate(10, 0, 5)
│ │ │ └ c = 5
│ │ └ b = 0
│ └ a = 10
File "my_script.py", line 5, in calculate
return a / b + c
──┘ └───
│ └ 0
└ 10
ZeroDivisionError: division by zero
Посмотрите внимательно: Loguru не просто показал, где произошла ошибка, он показал значения всех аргументов (a = 10, b = 0, c = 5) в момент падения! Это бесценная информация для отладки, которую вы получаете, добавив всего одну строку кода (@logger.catch).
Стандартный формат хорош, но иногда его нужно адаптировать под требования проекта. Это легко сделать с помощью параметра format в logger.add().
Вы можете собрать свой формат из готовых "кирпичиков":
from loguru import logger
import sys
# Удаляем стандартный обработчик, чтобы не было дублирования
logger.remove()
# Создаем свой, очень подробный формат
custom_format = (
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
"<level>{level: <8}</level> | "
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>"
)
logger.add(sys.stderr, format=custom_format)
logger.info("Лог в кастомном формате.")
Здесь мы добавили теги для цвета (<green>, <level>) и указали новые поля, например, {function} и {name}. Полный список доступных полей есть в официальной документации Loguru.
В современных системах логи часто собираются и анализируются машинами (например, в ELK Stack, Graylog или Datadog). Для этого они должны быть в структурированном формате, чаще всего — JSON.
С Loguru это делается элементарно — добавлением одного параметра: serialize=True.
from loguru import logger
logger.add("structured_data.log", serialize=True)
user_data = {"id": 123, "name": "John Doe"}
logger.info("Пользователь {user} обновил профиль", user=user_data)
В файле structured_data.log появится запись в формате JSON, идеально подходящая для парсинга:
{
"text": "Пользователь {'id': 123, 'name': 'John Doe'} обновил профильn",
"record": {
"elapsed": {"repr": "0:00:00.001000", "seconds": 0.001},
"exception": null,
"extra": {},
"file": {"name": "my_script.py", "path": "/path/to/my_script.py"},
"function": "<module>",
"level": {"icon": "ℹ️", "name": "INFO", "no": 20},
"line": 6,
"message": "Пользователь {'id': 123, 'name': 'John Doe'} обновил профиль",
"name": "__main__",
"process": {"id": 1234, "name": "MainProcess"},
"thread": {"id": 5678, "name": "MainThread"},
"time": {"repr": "2025-11-13T13:00:00.000000+03:00", "timestamp": 1762989600.0}
}
}
В сложных приложениях, например, в веб-сервисах, важно отслеживать цепочку событий, относящихся к одному запросу. Loguru позволяет "привязать" контекст к логгеру, и этот контекст будет добавляться во все последующие сообщения.
from loguru import logger
import uuid
# Создаем логгер с привязанным ID запроса
request_id = str(uuid.uuid4())
context_logger = logger.bind(request_id=request_id)
context_logger.info("Получен новый запрос.")
# ... какой-то код
context_logger.info("Данные из базы успешно получены.")
# ... еще код
context_logger.warning("Внешний API ответил с задержкой.")
В каждом из этих сообщений будет автоматически добавлено поле request_id, что позволит вам в системе сбора логов легко отфильтровать все события, связанные с одним конкретным запросом.
Эти продвинутые техники превращают Loguru из простого инструмента для записи сообщений в мощный фреймворк для отладки и мониторинга, который остается таким же простым в использовании.
Мы изучили мощные функции Loguru, но как грамотно внедрить его в полноценное приложение? Просто импортировать logger в каждом файле — это начало, но для создания надежной и масштабируемой системы стоит учесть несколько моментов.
Чтобы не настраивать логгер в разных частях вашего проекта, лучше всего создать один модуль, отвечающий за всю конфигурацию логирования. Это сделает ваши настройки последовательными и легко изменяемыми.
Создайте файл, например, app/logging_config.py:
# app/logging_config.py
import sys
from loguru import logger
def setup_logging():
"""
Настраивает логгер для всего приложения.
"""
# Удаляем стандартный обработчик, чтобы избежать дублирования
logger.remove()
# Добавляем обработчик для вывода в консоль (для разработки)
# Уровень DEBUG, цветной вывод
logger.add(
sys.stderr,
level="DEBUG",
format="<white>{time:HH:mm:ss}</white> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>",
colorize=True
)
# Добавляем обработчик для записи в файл (для продакшена)
# Уровень INFO, ротация, сжатие
logger.add(
"logs/app.log",
level="INFO",
rotation="10 MB",
retention="1 month",
compression="zip",
serialize=False, # В данном примере используем текстовый формат
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
)
logger.info("Конфигурация логирования завершена.")
Теперь в главном файле вашего приложения (например, main.py) вам нужно просто импортировать и вызвать эту функцию один раз при старте:
# main.py
from app.logging_config import setup_logging
from loguru import logger
# Вызываем настройку в самом начале работы приложения
setup_logging()
@logger.catch
def main_logic():
logger.info("Приложение начинает работу.")
# ... ваш основной код ...
a = 10
b = 0
result = a / b # Это вызовет ошибку, которую поймает @logger.catch
if __name__ == "__main__":
main_logic()
Такой подход гарантирует, что логирование будет работать одинаково во всех частях вашего проекта.
Что делать, если вы используете библиотеки (например, requests, SQLAlchemy, uvicorn), которые пишут свои логи через стандартный модуль logging? Loguru может элегантно "перехватить" эти сообщения и направить их в свои обработчики.
Для этого нужно создать специальный класс-обработчик и настроить logging на его использование. Этот код может показаться сложным, но вы можете просто скопировать его в свой конфигурационный файл — он работает как готовый рецепт.
# Добавьте это в ваш app/logging_config.py
import logging
class InterceptHandler(logging.Handler):
def emit(self, record):
# Получаем соответствующий уровень loguru
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Находим вызывающий код
frame, depth = logging.currentframe(), 2
while frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
# ... внутри функции setup_logging() добавьте эту строку:
def setup_logging():
# ... предыдущие настройки ...
# Настраиваем перехват логов из стандартного logging
logging.basicConfig(handlers=[InterceptHandler()], level=0)
logger.info("Стандартный logging перехвачен.")
Теперь все сообщения от сторонних библиотек будут проходить через Loguru и записываться в ваши файлы с нужным форматом и правилами ротации.
Функция @logger.catch и logger.exception() с параметром diagnose=True (который включен по умолчанию) — это мощнейший инструмент отладки. Но в продакшене он может стать источником утечки конфиденциальных данных! Он выводит значения всех переменных, а среди них могут оказаться пароли, ключи API, персональные данные пользователей.
Правило для продакшена: всегда отключайте диагностику.
# НЕ ДЕЛАЙТЕ ТАК В ПРОДАКШЕНЕ
@logger.catch
def process_user_data(user, password):
# ...
# ДЕЛАЙТЕ ТАК В ПРОДАКШЕНЕ
@logger.catch(diagnose=False)
def process_user_data(user, password):
# ...
То же самое касается и обработки исключений:
logger.opt(exception=True, diagnose=False).error("Произошла ошибка").
Хорошая новость: Loguru потокобезопасен "из коробки". Вам не нужно беспокоиться о блокировках при использовании логгера в многопоточных приложениях.
Для высоконагруженных или асинхронных приложений, где операции ввода-вывода (запись на диск) могут блокировать основной поток или event loop, Loguru предлагает параметр enqueue=True.
logger.add("high_load_app.log", enqueue=True)
С этой опцией сообщения сначала помещаются в очередь, а запись на диск происходит в отдельном процессе, не замедляя работу вашего основного приложения.
Следуя этим простым правилам, вы сможете построить надежную, информативную и безопасную систему логирования для проектов любого масштаба.
Прочитав статью, вы узнали, как сделать логирование в Python удобным и мощным. Теперь давайте применим эти знания на практике! Нажмите на каждую задачу, чтобы раскрыть её условие.
Цель: Убедиться, что Loguru установлен, и научиться выводить базовые сообщения.
Создайте новый Python-файл (например, task_1.py).
Импортируйте logger из библиотеки loguru.
Напишите код, который последовательно выводит в консоль сообщения следующих уровней:
DEBUG: "Это сообщение для отладки."
INFO: "Приложение успешно запущено."
SUCCESS: "Операция выполнена успешно!"
WARNING: "Внимание: используется устаревшая версия API."
ERROR: "Не удалось подключиться к базе данных."
Запустите скрипт и посмотрите на вывод в консоли. Обратите внимание, какие сообщения были выведены, а какие нет, и почему (вспомните про уровень по умолчанию).
Цель: Научиться настраивать запись логов в файл, используя logger.add(), и настроить автоматическую ротацию.
Создайте файл task_2.py.
Настройте логгер так, чтобы он записывал сообщения в файл app_actions.log.
Добавьте в настройку logger.add() следующие параметры:
Уровень логирования для файла должен быть INFO и выше.
Ротация: новый файл должен создаваться, как только текущий достигнет размера 1 KB (килобайт).
Сжатие: старые файлы логов должны сжиматься в формат zip.
Напишите цикл, который 100 раз выводит информационное сообщение (например, logger.info(f"Запись номер {i}")).
Запустите скрипт и проверьте папку с вашим проектом. Вы должны увидеть несколько файлов: текущий app_actions.log и несколько архивов .zip со старыми логами.
Цель: Практически применить самую мощную отладочную функцию Loguru для перехвата исключений.
Создайте файл task_3.py.
Напишите функцию divide_numbers(a, b), которая принимает два числа и возвращает результат их деления.
Оберните эту функцию декоратором @logger.catch.
Вызовите вашу функцию с параметрами, которые приведут к ошибке ZeroDivisionError (например, divide_numbers(10, 0)).
Запустите скрипт и изучите вывод в консоли. Обратите внимание, как Loguru показал не только ошибку, но и значения переменных a и b в момент её возникновения.
Цель: Научиться кастомизировать формат вывода сообщений для лучшей читаемости.
Создайте файл task_4.py.
Удалите стандартный обработчик с помощью logger.remove().
Добавьте новый обработчик для вывода в консоль (sys.stderr), который будет использовать следующий кастомный формат: {time:HH:mm:ss} | {level.icon} | {message}
{time:HH:mm:ss} — время в формате "часы:минуты:секунды".
{level.icon} — иконка, соответствующая уровню лога (например, ℹ️ для INFO).
{message} — само сообщение.
Выведите несколько сообщений разных уровней (INFO, WARNING, ERROR) и убедитесь, что они отображаются в консоли в вашем новом, лаконичном формате.
Цель: Симулировать настройку логирования для реального проекта, вынеся конфигурацию в отдельную функцию.
Создайте файл task_5_config.py. В нём определите функцию configure_logger().
Внутри этой функции настройте два обработчика (sinks):
Первый (для консоли): должен выводить сообщения уровня DEBUG и выше, быть цветным и использовать простой формат (например, {level} | {message}).
Второй (для файла): должен записывать сообщения уровня WARNING и выше в файл project_warnings.log в формате JSON (serialize=True).
Создайте главный файл task_5_main.py.
В task_5_main.py импортируйте функцию configure_logger() и вызовите её в самом начале.
После вызова конфигурации, напишите код, который генерирует несколько сообщений разных уровней (DEBUG, INFO, WARNING, ERROR).
Запустите task_5_main.py. Убедитесь, что:
В консоли отображаются все сообщения, начиная с DEBUG.
В файле project_warnings.log появились только сообщения WARNING и ERROR, записанные в формате JSON.
Анонс новых статей, полезные материалы, а так же если в процессе решения возникнут сложности, обсудить их или задать вопрос по статье можно в моём Telegram-сообществе [1].
Уверен, у вас все получится. Вперед, к практике!
Автор: enamored_poc
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/436687
Ссылки в тексте:
[1] моём Telegram-сообществе: https://t.me/+NlTdqmVuBkIzMDBi
[2] Источник: https://habr.com/ru/articles/966048/?utm_source=habrahabr&utm_medium=rss&utm_campaign=966048
Нажмите здесь для печати.