Вы когда-нибудь запускали программу и она вылетала с ошибкой? Никаких сообщений об ошибках, никаких подсказок, только тишина. Как понять, что пошло не так? В этом случае на помощь приходит ведение журнала.
Журналы отслеживают, что происходит внутри вашего кода, чтобы вам не приходилось гадать, когда что-то идёт не так. Они похожи на print
или console.log
, но более мощные.
В этой статье мы используем Python, чтобы создать и продемонстрировать вам несколько примеров кода для ведения журнала.
Прежде чем мы поговорим о журналах, давайте разберёмся в различных типах ошибок, с которыми вы можете столкнуться.
При создании приложения для производственной среды необходимо отображать ошибки в зависимости от их серьёзности. Существует несколько типов ошибок, и наиболее важные из них:
Теперь давайте перейдём к сути и разберёмся, что такое лесозаготовка.
Проще говоря, логирование — это процесс записи информации обо всём, что делает ваша программа. Записываемая информация может быть любой: от базовых сведений, таких как вызов функций, до более подробных, таких как отслеживание ошибок или проблем с производительностью.
Вы можете подумать: «Если логи выводят ошибки, информацию и так далее, я могу просто использовать операторы вывода. Зачем мне нужны логи?» Что ж, print
работает, но логи дают вам больше возможностей:
Это то, что print
не может сделать эффективно.
В Python модуль logging
создан специально для ведения журнала.
Давайте настроим несколько журналов, чтобы посмотреть, как они работают.
Чтобы начать использовать ведение журнала, нам нужно импортировать модуль:
import logging
Теперь вы можете начать регистрировать сообщения в своей программе. Вы можете использовать разные уровни регистрации в зависимости от важности сообщения. Напомним, что эти уровни (от наименее до наиболее важных):
Давайте запишем простое сообщение на каждом уровне:
logging.debug("This is a debug message") logging.info("This is an info message") logging.warning("This is a warning message") logging.error("This is an error message") logging.critical("This is a critical message")
При запуске вы увидите сообщение, выводимое на консоль, похожее на это:
Вы можете задаться вопросом, почему вы не видите сообщения DEBUG и INFO. Этому препятствует уровень ведения журнала по умолчанию.
По умолчанию уровень ведения журнала установлен на WARNING
. Это означает, что будут отображаться только сообщения с уровнем важности WARNING
или выше (то есть WARNING
, ERROR
, и CRITICAL
).
Чтобы увидеть сообщения debug
и info
, нам нужно установить уровень ведения журнала DEBUG
перед запуском кода.
Это означает, что нам нужно настроить логи. Для этого воспользуйтесь описанным ниже методом basicConfig
:
logging.basicConfig(level=logging.DEBUG)
Эта базовая конфигурация позволяет регистрировать сообщения на уровне DEBUG или выше. Вы можете изменить уровень в зависимости от типа необходимых вам журналов.
Теперь все журналы печатаются:
Теперь давайте сохраним эти журналы в файл, чтобы отслеживать ошибки и время их возникновения. Для этого обновите конфигурацию:
logging.basicConfig(filename='data_log.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
Здесь:
asctime
– Время, когда произошло событие.levelname
— Тип журнала (например, DEBUG, INFO).message
– Сообщение, которое мы выводим на экран.
Теперь, когда вы запустите программу, файл журнала будет создавать и сохранять ваши логи с указанием точного времени, типа ошибки и сообщения. Вот так:
Если вы работаете над крупным проектом, вам может понадобиться служебный логгер, который можно использовать в любом месте кода. Давайте создадим такой пользовательский логгер.
Сначала мы обновим basicConfig
так, чтобы он добавлял имя файла, номер строки и записывал всё, даже специальные символы:
logging.basicConfig( filename=log_file, level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s', filemode='w', encoding='utf-8' )
Объяснение:
encoding='utf-8'
— Обеспечивает регистрацию специальных символов.%(filename)s:%(lineno)d
— Регистрирует имя файла и номер строки, в которой был сгенерирован журнал.
Теперь давайте настроим пользовательский консольный регистратор:
console_handler = logging.StreamHandler() console_handler.setLevel(logging.DEBUG) console_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s') # Added line number console_handler.setFormatter(console_formatter) logging.getLogger().addHandler(console_handler)
Эта настройка выполняет следующее:
console_handler
: Отправляет сообщения журнала на консоль (стандартный вывод).console_formatter
: Форматирует сообщение журнала с указанием времени, уровня, имени файла, номера строки и самого сообщения.logging.getLogger().addHandler(console_handler)
: Добавляет пользовательский обработчик в корневой журнал, чтобы сообщения журнала выводились на консоль.
import logging import os from datetime import datetime def setup_daily_logger(): base_dir = os.path.dirname(os.path.abspath(__file__)) log_dir = os.path.join(base_dir, 'logs') os.makedirs(log_dir, exist_ok=True) current_time = datetime.now().strftime("%m_%d_%y_%I_%M_%p") log_file = os.path.join(log_dir, f"{current_time}.log") logging.basicConfig( filename=log_file, level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s', filemode='w', encoding='utf-8' ) console_handler = logging.StreamHandler() console_handler.setLevel(logging.DEBUG) console_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s') # Added line number console_handler.setFormatter(console_formatter) logging.getLogger().addHandler(console_handler) return logging.getLogger(__name__)
Теперь при каждом запуске программы в папке logs
будет создаваться новый файл журнала. При каждом запуске программы будет создаваться новый файл журнала с уникальной отметкой времени.
Вот так:
Эти журналы дадут вам чёткое представление о поведении вашей программы и помогут в отладке.
Надеюсь, эта статья помогла вам лучше понять логи и их важность в программировании.
Теперь, когда вы понимаете, что такое логи и как их настроить в Python, давайте рассмотрим примеры из реальной жизни.
Вот пример бота, созданного для сбора данных с крупнейшего в Корее сайта о недвижимости.
Один из методов в классе этого бота использует логирование, чтобы отслеживать, правильно ли бот выбирает провинцию.
Здесь:
Теперь давайте посмотрим, как ведение журнала помогает в парсинге групп Facebook.
Здесь вы видите точное имя файла и номер строки, в которой возникает ошибка.
Как только мы выявили и устранили проблему, бот снова начал работать.
Он фиксирует каждую деталь в журнале, экономя часы отладки за счёт определения места возникновения ошибок.
Ведение журналов — это одна из тех вещей, о которых никто не задумывается, пока что-нибудь не сломается. Но когда это происходит, журналы становятся вашим лучшим другом.
Запомните:
Не забудьте добавить ведение журнала в свой код. Вы потом будете себя благодарить!