Модуль logging в Python представляет собой встроенный инструмент для ведения логов. Это гибкий механизм записи сообщений (логов) в различные места, такие как файлы, консоль, потоки и т. д. Он обеспечивает структурированный способ организации информации о работе программы, что полезно при отладке, мониторинге и анализе работы приложения.
Раньше я создава логи самостоятельно в простой текстовый файл. Но с библиотекой logging логирование будет намного эффективнее, так как можно создавать файлы с разным уровнем важности информации.
logging.getLogger(name).logger.addHandler(handler).handler.setFormatter(formatter).DEBUG, INFO, WARNING, ERROR, и CRITICAL. Устанавливая уровень логгирования, вы можете контролировать, какие сообщения будут записаны.В Python существует несколько способов ведения логов. Один из наиболее популярных и удобных способов — использование модуля logging, встроенного в стандартную библиотеку Python. Вот примеры использования:
Рассмортим самый простой пример использования библиотеки logging
import logging
# Настройка конфигурации логгера
logging.basicConfig(filename='example.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
# Примеры использования логгера
def example_function():
try:
result = 10 / 0
except Exception as e:
# Запись ошибки в лог
logging.error(f"An error occurred: {e}", exc_info=True)
def another_function():
# Запись информационного сообщения в лог
logging.info("This is an informational message.")
def main():
# Запись отладочной информации в лог
logging.debug("This is a debug message.")
example_function()
another_function()
if __name__ == "__main__":
main() Объяснения к коду:
logging.basicConfig: Эта функция выполняет базовую настройку логгера. В данном примере указано имя файла лога (example.log), уровень логгирования (DEBUG — самый подробный уровень), и формат сообщений лога.logging.debug, logging.info, logging.warning, logging.error, logging.critical: Это методы для записи сообщений разных уровней в лог. Уровень логгирования можно настроить, чтобы записывать только сообщения с определенного уровня и выше. А можно записывать разные уровни в разные файлы. Об этом дальше.exc_info=True: Этот параметр добавляет информацию об исключении в лог, если произошла ошибка.При использовании логгера, вы можете легко настроить уровень детализации лога и перенаправить вывод в файл, консоль или другие места. Кроме того, логгеры можно конфигурировать для отправки логов на удаленный сервер или в различные хранилища, что делает их мощным инструментом для отладки и мониторинга вашего приложения.
logging.basicConfig(filename='example.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') Конфигурация (настройка) логгера выполняется с использованием функции basicConfig из модуля logging. Давайте подробно рассмотрим параметры этой функции:
filename='example.log': Этот параметр указывает имя файла, в который будут записываться логи. В данном случае, логи будут записываться в файл с именем ‘example.log’. Если вы не указываете filename, логи будут выводиться в стандартный поток вывода (консоль).level=logging.DEBUG: Этот параметр устанавливает уровень логгирования. Уровень определяет, какие сообщения будут записаны. В данном случае, установлен уровень DEBUG, что означает, что будут записаны все сообщения, начиная от уровня DEBUG и выше. Вы можете выбрать из уровней логгирования, таких как DEBUG, INFO, WARNING, ERROR, и CRITICAL, в порядке увеличения уровня критичности.format='%(asctime)s - %(levelname)s - %(message)s': Этот параметр определяет формат сообщений лога. В данном случае, используется формат, который включает время записи лога (%(asctime)s), уровень логгирования (%(levelname)s), и само сообщение (%(message)s). Время записи лога форматируется в соответствии с форматом времени, и это позволяет вам видеть, когда каждое сообщение было записано.Пример формата времени в %(asctime)s:
%Y: Год с веком в виде полного числа.%m: Месяц как число (01-12).%d: День месяца как число (01-31).%H: Час (00-23).%M: Минуты (00-59).%S: Секунды (00-59).Таким образом, формат '%(asctime)s - %(levelname)s - %(message)s' создает записи лога следующего вида: «2023-11-14 15:30:00 — DEBUG — This is a debug message.»
Level -уровни логирования логов.
В приведенном примере выше, строка с вызовом logging.debug("This is a debug message.") представляют собой пример отладочной информации. Содержание информации задается программистом. Данная инфоррмация запишется в логи, при уровне логирования DEBUG. Если бы уровень был установлен на более высокий, например, INFO, сообщение с уровнем DEBUG не было бы записано. Уровень логгирования можно регулировать, чтобы включить или выключить запись сообщений определенного уровня. И это очень удобно на разных этапах тестирования программы.
По сути логи — это сообщения, заданные создателем программы. Но то какое сообщения будет записано в логи — будет зависить от уровня логирования.
DEBUG: Наиболее подробные сообщения, предназначенные для отладки. Используются для записи деталей выполнения кода.INFO: Информационные сообщения о ходе выполнения программы. Подходит для отображения основной информации о процессе работы приложения.WARNING: Предупреждения, которые не являются фатальными, но требуют внимания. Используются для выявления потенциальных проблем.ERROR: Сообщения об ошибках, которые не позволяют продолжить выполнение программы.CRITICAL: Критические ошибки, которые говорят о невозможности продолжения выполнения программы.При установке уровня логирования записываться будут все сообщения с установленным уровня и выше. Например, если уровень установлен в DEBUG, то все сообщения с уровнем DEBUG, INFO, WARNING, ERROR, и CRITICAL будут записаны. Если уровень установлен в INFO, то будут записаны только сообщения с уровнем INFO, WARNING, ERROR, и CRITICAL, и так далее.
import logging
# Настройка логгера с уровнем INFO и записью в файл info.log
logger_info = logging.getLogger('info_logger')
logger_info.setLevel(logging.INFO)
file_handler_info = logging.FileHandler('info.log')
file_handler_info.setLevel(logging.INFO)
formatter_info = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler_info.setFormatter(formatter_info)
logger_info.addHandler(file_handler_info)
# Настройка логгера с максимальным уровнем DEBUG и записью в файл debug.log
logger_debug = logging.getLogger('debug_logger')
logger_debug.setLevel(logging.DEBUG)
file_handler_debug = logging.FileHandler('debug.log')
file_handler_debug.setLevel(logging.DEBUG)
formatter_debug = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler_debug.setFormatter(formatter_debug)
logger_debug.addHandler(file_handler_debug)
def main():
# Примеры использования логгеров
logger_info.info("This is an informational message.")
logger_debug.debug("This is a debug message.") В этом примере создаются два логгера: logger_info с уровнем INFO и записью в файл info.log, а также logger_debug с максимальным уровнем DEBUG и записью в файл debug.log. Вы можете использовать эти логгеры по отдельности в различных частях вашего кода в зависимости от того, какую информацию вы хотите записывать.
Каждый логгер имеет свой собственный уровень логгирования, и вы можете настроить форматирование, обработчики и другие параметры для каждого из них по отдельности.
Инициализация логгера обычно выполняется в основном модуле программы или в специальном модуле, который выполняет роль настройщика (configurator). Это место часто называют «точкой входа» (entry point) в ваше приложение. Инициализация логгера лучше проводить один раз, при запуске программы.
Примерно так может выглядеть структура инициализации логгера в основном файле вашей программы:
# main.py
import logging
from my_module import example_function, another_function
def setup_logging():
logging.basicConfig(filename='main.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
def main():
# Инициализация логгера
setup_logging()
# Запись отладочной информации в лог
logging.debug("This is a debug message.")
example_function()
another_function()
if __name__ == "__main__":
main() Теперь, чтобы использовать один и тот же логгер в других файлах, вам необходимо сделать следующее:
# my_module.py
import logging
# Получение логгера с тем же именем, что и в основном файле
logger = logging.getLogger(__name__)
def example_function():
try:
result = 10 / 0
except Exception as e:
# Запись ошибки в лог
logger.error(f"An error occurred: {e}", exc_info=True) В этом примере __name__ в getLogger(__name__) будет заменено на имя текущего модуля, что гарантирует уникальность логгера в рамках вашего приложения.
Конфигуратор для логгера может представлять собой отдельный модуль, который содержит функцию или класс для настройки логгера. Вот пример конфигуратора:
import logging
def setup_logger(log_file, log_level=logging.DEBUG):
# Создаем логгер
logger = logging.getLogger()
logger.setLevel(log_level)
# Проверяем наличие обработчиков, чтобы обрабочик использовался один раз
if logger.hasHandlers():
logger.handlers = []
# Создаем обработчик для записи в файл
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(log_level)
# Создаем форматтер
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# Добавляем обработчик к логгеру
logger.addHandler(file_handler)
return logger Теперь, в основном файле вашей программы (главном файле) вы можете использовать этот конфигуратор следующим образом:
# main.py
from logger_configurator import setup_logger
from my_module import example_function, another_function
def main():
# Используем конфигуратор для настройки логгера
logger = setup_logger('main.log', log_level=logging.DEBUG)
# Запись отладочной информации в лог
logger.debug("This is a debug message.")
example_function()
another_function()
if __name__ == "__main__":
main() Таким образом, конфигуратор setup_logger настраивает логгер с уровнем логгирования по умолчанию DEBUG и записью в файл ‘main.log’. Вы можете вызывать этот конфигуратор в каждом модуле, где вам необходим логгер, чтобы использовать один и тот же логгер по всему приложению.
# my_module.py
from logger_configurator import setup_logger
# Используем конфигуратор для настройки логгера в модуле
logger = setup_logger('my_module.log', log_level=logging.INFO)
def example_function():
try:
result = 10 / 0
except Exception as e:
# Запись ошибки в лог
logger.error(f"An error occurred: {e}", exc_info=True) Таким образом, каждый модуль может использовать свой уникальный файл для записи логов, и все логгеры будут настроены согласованно в рамках вашего приложения.
Для записи логов в каждом файле, где они нужны, вы должны инициализировать логгер.И чтобы избежать избыточного кода и создания множества логгеров с одинаковыми настройками, часто используется шаблон (отдельный модуль) с использованием функции конфигурации.
В этом шаблоне есть главный файл, где вызывается функция конфигурации логгера. Затем в других файлах этот логгер используется без повторной инициализации. Это создает централизованный логгер с общими настройками по всему приложению.
Такой подход помогает избежать дублирования кода и обеспечивает единообразное логгирование по всему приложению.
И напоследок мой код конфигуратора, который фильтрует сообщения INFO и ERROR и записывает их в отдельные файлы, а также выводит логи в консоль.
import logging
import os
def setup_logger():
log_folder = '02-log'
# Создаем общий логгер
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# Чтобы логи не дублировались сбрасываем все обработчики
if logger.hasHandlers():
logger.handlers = []
# Создаем обработчик для общих логов
file_handler = logging.FileHandler(os.path.join(log_folder, 'debug.log'))
formatter = logging.Formatter('[%(asctime)s] %(levelname)s | %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Создаем отдельные обработчики для INFO и ERROR
info_handler = logging.FileHandler(os.path.join(log_folder, 'info.log'))
error_handler = logging.FileHandler(os.path.join(log_folder, 'error.log'))
# Определяем фильтры
info_filter = logging.Filter()
error_filter = logging.Filter()
# Устанавливаем фильтры для INFO и ERROR обработчиков
info_filter.filter = lambda record: record.levelno == logging.INFO
error_filter.filter = lambda record: record.levelno == logging.ERROR
# Присваиваем фильтры обработчикам
info_handler.addFilter(info_filter)
error_handler.addFilter(error_filter)
# Устанавливаем форматтер для обработчиков
info_handler.setFormatter(formatter)
error_handler.setFormatter(formatter)
# Добавляем обработчики к логгеру
# Добавляем обработчик только если его еще нет
if not any(isinstance(h, logging.FileHandler) and h.baseFilename == 'error.log' for h in logger.handlers):
logger.addHandler(error_handler)
if not any(isinstance(h, logging.FileHandler) and h.baseFilename == 'info.log' for h in logger.handlers):
logger.addHandler(info_handler)
# Создаем обработчик для вывода сообщений в консоль
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger Если при открытие csv файла с помощью excel У все поехали ячейки - это простой… Read More
Простые шаги как происходит Загрузка проекта на Github и Автодеплой на сервер Сделайте работу проще! Read More
Миграция базы данных - помогают с этим библиотеки SQLAlchemy и Alembic. Read More
Основные Команды Git, которые точно пригодятся. Сохрани себе шпаргалку Git Read More
Установка PostgreSQL на сервер Read More
Как создать PrimaryKey в талице базы данных SQL [РЕШЕНО] Ошибка relation tablename_id_seq doesn't exist Read More