Введение: Боль и страдания от print() и стандартного logging
Если вы пишете на 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 может сделать ваше логирование не только мощным, но и по-настоящему красивым и удобным.
Часть 1: Первое знакомство с Loguru — магия "из коробки"
Итак, мы оставили позади боль от print() и сложность logging. Давайте посмотрим, что предлагает Loguru и почему его называют "логированием для удовольствия".
Установка: один шаг до магии
Как и положено современному Python-пакету, установка предельно проста и выполняется одной командой в терминале:
pip install loguru
Всё, библиотека готова к работе. Никаких зависимостей, никаких сложных настроек окружения.
"Hello, Loguru!": начинаем за 5 секунд
Помните, сколько кода нужно было для базовой настройки 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 "из коробки". А ведь мы еще даже не начали знакомиться с его основными возможностями
Часть 2: Основные возможности на практических примерах
Мы убедились, что Loguru прекрасен "из коробки". Но его настоящая сила раскрывается, когда мы начинаем использовать его основные функции. И здесь Loguru остается верен своему принципу: максимум пользы при минимуме кода.
Уровни логирования: управляем потоком информации
Как мы уже видели, Loguru поддерживает стандартные уровни важности сообщений:
TRACE(самый подробный)DEBUGINFOSUCCESS(приятное дополнение для успешных операций)WARNINGERRORCRITICAL
По умолчанию в консоль выводятся сообщения от 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. Это невероятно удобно.
Форматирование в стиле f-string
Еще одна мелочь, которая делает жизнь разработчика проще. Loguru использует для форматирования строк фигурные скобки, как в f-strings, что гораздо читабельнее и привычнее, чем старый %-стиль.
user_id = 123
status = "success"
# Привычный и читаемый синтаксис
logger.info("Аутентификация для пользователя {id} прошла со статусом: {status}", id=user_id, status=status)
Вывод будет таким:
... | INFO | ... - Аутентификация для пользователя 123 прошла со статусом: success
Мы рассмотрели базовые, но самые часто используемые возможности Loguru. Уже на этом этапе видно, насколько он упрощает и ускоряет разработку. Но это еще не все — в следующей части мы погрузимся в продвинутые техники, которые сделают вашу отладку по-настоящему волшебной.
Часть 3: Продвинутые техники для настоящих профи
Мы освоили основы, которые уже делают работу с логами приятнее. Но Loguru был создан не только для удобства — он предоставляет мощнейшие инструменты для отладки, которые могут сэкономить вам часы поиска ошибок. Давайте рассмотрим функции, которые отличают новичка от профессионала.
1. Идеальная отладка исключений
Это, пожалуй, главная "киллер-фича" 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).
2. Кастомизация формата логов
Стандартный формат хорош, но иногда его нужно адаптировать под требования проекта. Это легко сделать с помощью параметра 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.
3. Структурированное логирование (JSON)
В современных системах логи часто собираются и анализируются машинами (например, в 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}
}
}
4. Добавление контекста с помощью bind()
В сложных приложениях, например, в веб-сервисах, важно отслеживать цепочку событий, относящихся к одному запросу. 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 из простого инструмента для записи сообщений в мощный фреймворк для отладки и мониторинга, который остается таким же простым в использовании.
Часть 4: Loguru в реальном проекте: Советы и лучшие практики
Мы изучили мощные функции Loguru, но как грамотно внедрить его в полноценное приложение? Просто импортировать logger в каждом файле — это начало, но для создания надежной и масштабируемой системы стоит учесть несколько моментов.
1. Создайте централизованную конфигурацию
Чтобы не настраивать логгер в разных частях вашего проекта, лучше всего создать один модуль, отвечающий за всю конфигурацию логирования. Это сделает ваши настройки последовательными и легко изменяемыми.
Создайте файл, например, 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()
Такой подход гарантирует, что логирование будет работать одинаково во всех частях вашего проекта.
2. Интеграция с библиотеками, использующими стандартный logging
Что делать, если вы используете библиотеки (например, 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 и записываться в ваши файлы с нужным форматом и правилами ротации.
3. Безопасность прежде всего: осторожно с данными в продакшене!
Функция @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("Произошла ошибка").
4. Потокобезопасность и асинхронность
Хорошая новость: Loguru потокобезопасен "из коробки". Вам не нужно беспокоиться о блокировках при использовании логгера в многопоточных приложениях.
Для высоконагруженных или асинхронных приложений, где операции ввода-вывода (запись на диск) могут блокировать основной поток или event loop, Loguru предлагает параметр enqueue=True.
logger.add("high_load_app.log", enqueue=True)
С этой опцией сообщения сначала помещаются в очередь, а запись на диск происходит в отдельном процессе, не замедляя работу вашего основного приложения.
Следуя этим простым правилам, вы сможете построить надежную, информативную и безопасную систему логирования для проектов любого масштаба.
Домашнее задание: Закрепляем Loguru на практике
Прочитав статью, вы узнали, как сделать логирование в Python удобным и мощным. Теперь давайте применим эти знания на практике! Нажмите на каждую задачу, чтобы раскрыть её условие.
Задача 1: Первая настройка и знакомство
Цель: Убедиться, что Loguru установлен, и научиться выводить базовые сообщения.
Создайте новый Python-файл (например,
task_1.py).Импортируйте
loggerиз библиотекиloguru.-
Напишите код, который последовательно выводит в консоль сообщения следующих уровней:
DEBUG: "Это сообщение для отладки."INFO: "Приложение успешно запущено."SUCCESS: "Операция выполнена успешно!"WARNING: "Внимание: используется устаревшая версия API."ERROR: "Не удалось подключиться к базе данных."
Запустите скрипт и посмотрите на вывод в консоли. Обратите внимание, какие сообщения были выведены, а какие нет, и почему (вспомните про уровень по умолчанию).
Задача 2: Запись логов в файл с ротацией
Цель: Научиться настраивать запись логов в файл, используя logger.add(), и настроить автоматическую ротацию.
Создайте файл
task_2.py.Настройте логгер так, чтобы он записывал сообщения в файл
app_actions.log.-
Добавьте в настройку
logger.add()следующие параметры:Уровень логирования для файла должен быть
INFOи выше.Ротация: новый файл должен создаваться, как только текущий достигнет размера
1 KB(килобайт).Сжатие: старые файлы логов должны сжиматься в формат
zip.
Напишите цикл, который 100 раз выводит информационное сообщение (например,
logger.info(f"Запись номер {i}")).Запустите скрипт и проверьте папку с вашим проектом. Вы должны увидеть несколько файлов: текущий
app_actions.logи несколько архивов.zipсо старыми логами.
Задача 3: Магия отладки с @logger.catch
Цель: Практически применить самую мощную отладочную функцию Loguru для перехвата исключений.
Создайте файл
task_3.py.Напишите функцию
divide_numbers(a, b), которая принимает два числа и возвращает результат их деления.Оберните эту функцию декоратором
@logger.catch.Вызовите вашу функцию с параметрами, которые приведут к ошибке
ZeroDivisionError(например,divide_numbers(10, 0)).Запустите скрипт и изучите вывод в консоли. Обратите внимание, как Loguru показал не только ошибку, но и значения переменных
aиbв момент её возникновения.
Задача 4: Создание собственного формата логов
Цель: Научиться кастомизировать формат вывода сообщений для лучшей читаемости.
Создайте файл
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) и убедитесь, что они отображаются в консоли в вашем новом, лаконичном формате.
Задача 5: Сборка всего вместе — конфигурация для проекта
Цель: Симулировать настройку логирования для реального проекта, вынеся конфигурацию в отдельную функцию.
Создайте файл
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-сообществе.
Уверен, у вас все получится. Вперед, к практике!
1024rk
После публикации вы получите $0.15 на ваш счёт от OpenAI. Не забудьте удалить последний абзац перед публикацией.
enamored_poc Автор
Я заранее пишу статью!) Расписываю сначала план, а потом начинаю ее заполнять. Я хотел туда поставить картинку но забыл)
1024rk
Ага, верим.