Logging в Python

Logging (журналирование) является важной частью разработки программного обеспечения. Он позволяет записывать сообщения об ошибках, предупреждениях, информационных и отладочных данных для последующего анализа и отладки.

В языке Python для журналирования используется стандартный модуль logging.

Для использования модуля logging в Python необходимо его импортировать с помощью команды import logging.

Далее необходимо настроить журналирование, определить уровень логирования и задать обработчики сообщений. Наиболее часто используемый способ настройки журналирования - использование файла конфигурации.

Пример файла конфигурации logging.conf:

[loggers]
keys=root,sampleLogger

[handlers]
keys=consoleHandler, fileHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler

[logger_sampleLogger]
level=DEBUG
handlers=consoleHandler,fileHandler
qualname=sampleLogger
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('app.log','w')

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=%Y-%m-%d %H:%M:%S

В данном примере определена конфигурация с двумя логгерами - root и sampleLogger, двумя обработчиками - consoleHandler и fileHandler, и одним форматтером - simpleFormatter. Каждая секция в файле конфигурации соответствует определенному объекту logging.

После настройки журналирования необходимо импортировать модуль logging.config и вызвать метод fileConfig() или dictConfig(), передав ему путь к файлу конфигурации или словарь с настройками.

Пример использования файла конфигурации:

import logging

logging.config.fileConfig('logging.conf')

logger = logging.getLogger('sampleLogger')
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

В данном примере мы импортируем модуль logging.config и вызываем метод fileConfig(), передавая ему путь к файлу конфигурации. Затем мы создаем логгер с именем sampleLogger и вызываем методы для записи сообщений разного уровня.

После выполнения этого кода сообщения будут записаны в файл app.log и выведены на консоль в соответствии с настройками в файле конфигурации.

Уровни логирования

Уровни логирования являются важным аспектом при разработке программного обеспечения. Они позволяют указать, насколько подробными могут быть сообщения, записываемые в журнал приложения. Уровни логирования помогают разработчикам контролировать количество информации, отображаемой в журнале, и облегчают поиск и анализ проблем, возникающих в процессе работы программы.

В программировании существуют различные уровни логирования, но наиболее распространенные из них следующие:

  • CRITICAL: Самый высокий уровень логирования. Используется для сообщений, указывающих на критическую ситуацию, которая требует мгновенного вмешательства разработчика. Примеры: сбой приложения, неожиданная ошибка.
  • ERROR: Уровень ошибки. Используется для сообщений об ошибках, которые приводят к невозможности выполнения определенной операции или имеют серьезные последствия. Примеры: некорректные входные данные, ошибки базы данных.
  • WARNING: Уровень предупреждений. Используется для сообщений о потенциальных проблемах или неправильном использовании функций. Примеры: несовпадение версий библиотек, недостаточная память.
  • INFO: Уровень информации. Используется для отчетов о нормальной работе приложения. Примеры: статистика выполненных операций, успешное подключение к базе данных.
  • DEBUG: Самый низкий уровень логирования. Используется для подробной отладочной информации, которая помогает разработчику исследовать проблемы и проверять работу программы шаг за шагом. Примеры: значения переменных, вызовы функций.

Модуль logging поддерживает следующие уровни логирования:

  • DEBUG: наиболее детальная информация для отладки
  • INFO: информационные сообщения
  • WARNING: предупреждения
  • ERROR: сообщения об ошибках
  • CRITICAL: критические ошибки, которые могут привести к остановке программы

Форматирование сообщений лога в модуле logging

Вот несколько доступных переменных для форматирования логов:

  • asctime: Дата и время создания сообщения лога. Формат может быть сконфигурирован с помощью метода Formatter в объекте logging.
  • levelname: Уровень сообщения лога (например, DEBUG, INFO, WARNING, ERROR, CRITICAL).
  • name: Имя логгера, который создал запись лога.
  • message: Текст сообщения лога.
  • pathname: Полный путь к файлу, в котором произошло запись лога.
  • filename: Имя файла, в котором произошло запись лога.
  • module: Имя модуля, в котором произошло запись лога.
  • lineno: Номер строки, в которой произошло запись лога.
  • funcName: Имя функции, которая вызвала запись лога.
  • process: Идентификатор процесса, в котором произошло запись лога.
  • thread: Идентификатор потока, в котором произошло запись лога.

Для форматирования сообщений лога можно использовать строку с плейсхолдерами %([имя_переменной])s. Переменная будет заменена на соответствующее значение при записи сообщения в лог. Например, для записи сообщения с указанием даты и времени можно использовать следующий формат:

import logging

logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)
logger = logging.getLogger()
logger.info('Сообщение для записи в лог')

В результате выполнения данного кода будет создана запись в лог с указанием текущей даты и времени перед текстом сообщения.

Также можно использовать другие переменные, указанные выше, для создания более информативных записей в логе. Например, можно добавить имя логгера, имя файла и номер строки в формат записи лога:

import logging

logging.basicConfig(format='%(asctime)s - %(levelname)s - %(name)s - %(filename)s:%(lineno)d - %(message)s', level=logging.INFO)
logger = logging.getLogger('my_logger')
logger.info('Сообщение для записи в лог')

В результате выполнения данного кода будет создана запись в лог с указанием даты и времени, уровня сообщения лога, имени логгера, имени файла и номера строки перед текстом сообщения.

Форматирование сообщений лога в модуле logging позволяет создавать информативные и разнообразные записи в лог, которые могут быть использованы для анализа и отладки приложения.

Логирование с классом FileHandler

Класс FileHandler в модуле logging предоставляет возможность записи логов в файл. Он является одним из множества классов обработчиков, которые могут быть использованы для направления логов в различные источники, такие как файлы, консоль, сеть, база данных и другие.

Преимущества использования FileHandler для логирования:

  • Возможность сохранения логов в файле, что позволяет сохранять их на длительное время и восстанавливать историю происходящих событий.
  • Гибкость настройки формата вывода логов в файле.
  • Возможность настройки уровней логирования, чтобы записывать только наиболее важные сообщения или все сообщения.

Пример использования класса FileHandler:

import logging

# Создание объекта логгера
logger = logging.getLogger("my_logger")
logger.setLevel(logging.DEBUG)

# Создание объекта обработчика файла
file_handler = logging.FileHandler("my_logs.log")

# Настройка формата вывода логов
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

# Установка уровня логирования
file_handler.setLevel(logging.ERROR)

# Добавление обработчика файла к логгеру
logger.addHandler(file_handler)

# Запись логов
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
logger.critical("Critical message")

Код выше создает логгер с именем "my_logger" и устанавливает его уровень логирования на DEBUG. Затем создается объект FileHandler с именем файла "my_logs.log" для записи логов.

Настраивается формат вывода логов и устанавливается уровень логирования для файлового обработчика. В данном примере установлен уровень ERROR, что означает, что будут записываться только сообщения об ошибках и критические сообщения.

Обработчик файла file_handler добавляется к логгеру logger. Затем можно использовать методы логгера, такие как debug(), info(), warning(), error() и critical(), чтобы записать соответствующую категорию логов в файл "my_logs.log".

После выполнения кода в файле "my_logs.log" будут записаны только сообщения об ошибках и критические сообщения.

Использование класса FileHandler позволяет эффективно логировать информацию в файле, что может быть полезным для отладки и анализа работы программы на более поздних этапах разработки.

Логгирование с использованием класса StreamHandler

Модуль logging в языке Python предоставляет возможности для логгирования (записи) сообщений во время выполнения программы. Он предлагает различные классы для настройки и управления выводом сообщений лога.

Один из таких классов - StreamHandler, который позволяет записывать сообщения лога в любой поток (например, в поток вывода данных sys.stdout). Это может быть полезно, когда необходимо выводить логи в консоль или в другое место, доступное через поток.

Пример использования класса StreamHandler вместе с модулем logging:

import logging

# Создаем экземпляр объекта логгера
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)

# Создаем экземпляр объекта StreamHandler и устанавливаем уровень логирования
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('Отладочное сообщение')
logger.info('Информационное сообщение')
logger.warning('Предупреждение')
logger.error('Ошибка')
logger.critical('Критическая ошибка')

В данном примере мы сначала создаем экземпляр объекта logger с именем "my_logger" и устанавливаем уровень логирования на DEBUG. Затем мы создаем экземпляр объекта StreamHandler, устанавливаем уровень логирования на DEBUG и добавляем созданное форматирование. Затем мы добавляем созданный обработчик handler к нашему логгеру logger.

Далее мы можем использовать наш логгер logger для записи различных уровней сообщений лога. В данном примере используются уровни DEBUG, INFO, WARNING, ERROR и CRITICAL. Каждое сообщение лога будет отформатировано с использованием заданного в форматировании шаблона и выведено в поток вывода данных (в данном случае - в стандартный поток вывода).

Обратите внимание, что метод debug() применим только если уровень логирования логгера установлен на DEBUG или на более низкий уровень. Аналогично, методы info(), warning(), error() и critical() будут работать в зависимости от уровня логирования.

Вы можете настроить класс StreamHandler для записи в любой другой поток, указав его в качестве аргумента при создании объекта StreamHandler. Например, вместо потока вывода данных (sys.stdout) вы можете использовать файловый поток или любой другой поддерживаемый поток.

Использование класса StreamHandler вместе с модулем logging предоставляет мощные возможности для контроля и анализа работы программы через запись сообщений лога в желаемый поток вывода. Это может быть важным инструментом при разработке и отладке программного обеспечения.

Логгирование с использованием пользовательского обработчика логгов

Для создания пользовательского обработчика логов необходимо унаследовать класс от базового обработчика logging.Handler. В пользовательском обработчике можно определить, какую информацию записывать и куда её записывать.

Пример кода пользовательского обработчика CustomHandler:

import logging

class CustomHandler(logging.Handler):
    def __init__(self, filename):
        super().__init__()
        self.filename = filename

    def emit(self, record):
        log_entry = self.format(record)

        # Здесь можно определить, куда и как записывать логи
        with open(self.filename, 'a') as f:
            f.write(log_entry + '\n')

В приведенном примере пользовательский обработчик CustomHandler наследуется от logging.Handler. В методе emit определено, что записывать логи будем в файл, указанный в конструкторе обработчика.

Настройка и использование пользовательского обработчика логов

После создания пользовательского обработчика логов, его можно добавить в логгер, чтобы начать записывать логи в указанное место.

Пример кода, добавляющего пользовательский обработчик в логгер:

import logging

# Создание экземпляра пользовательского обработчика
custom_handler = CustomHandler('app.log')

# Создание логгера
logger = logging.getLogger('my_logger')

# Установка уровня логгирования
logger.setLevel(logging.DEBUG)

# Добавление обработчика логов
logger.addHandler(custom_handler)

# Пример записи логов
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')

В приведенном примере пользовательский обработчик custom_handler создается с указанием имени файла, в который будут записываться логи. Затем создается логгер logger, устанавливается уровень логгирования и добавляется обработчик логов custom_handler.

После этого можно начинать записывать логи с помощью методов логгера, таких как debug(), info(), warning(), error() и critical().

Использование пользовательского обработчика логов в модуле logging позволяет настроить запись логов по своим предпочтениям и в нужное место. Создавая собственный обработчик, можно определить, какую информацию записывать и куда ее записывать, что сделает логгирование более гибким и адаптированным под конкретные потребности приложения.

Класс Filter модуля logging в Python

Класс Filter в модуле logging языка Python предоставляет возможность выполнять фильтрацию записей журнала на основе определенных условий. Фильтры позволяют выбирать только нужные записи для вывода или сохранения.

Для использования класса Filter необходимо создать пользовательский класс, который будет наследоваться от класса Filter. В этом классе нужно определить метод filter(record), который будет выполнять фильтрацию. Метод filter(record) должен принимать один параметр - объект LogRecord, который содержит информацию о текущей записи журнала.

В методе filter(record) необходимо реализовать логику фильтрации и возвращать True или False в зависимости от результата. Если метод возвращает True, то запись будет сохранена или выведена в журнал. Если метод возвращает False, то запись будет проигнорирована.

Пример создания фильтра с использованием класса Filter:

import logging

class CustomFilter(logging.Filter):
    def filter(self, record):
        # Фильтрация записей по уровню логирования
        if record.levelname == 'ERROR':
            return True
        else:
            return False

# Создание объекта логгера
logger = logging.getLogger()

# Создание объекта фильтра
custom_filter = CustomFilter()

# Добавление фильтра в логгер
logger.addFilter(custom_filter)

# Логирование
logger.error('Это сообщение об ошибке')
logger.warning('Это предупреждение')
logger.info('Это информационное сообщение')

В данном примере создается пользовательский класс CustomFilter, который наследуется от класса Filter. В методе filter(record) определена фильтрация записей по уровню логирования. Если уровень логирования равен "ERROR", то метод возвращает True и запись сохраняется или выводится в журнал.

Затем создается объект логгера и объект фильтра. Фильтр добавляется в логгер с помощью метода addFilter(). В результате, только записи с уровнем логирования "ERROR" будут сохранены или выведены в журнал.

Вывод программы:

ERROR:root:Это сообщение об ошибке

Класс Formatter модуля logging в Python

Один из ключевых классов модуля logging - Formatter. Этот класс позволяет настраивать формат вывода логов, т.е. указывать, какая информация будет содержаться в каждой записи лога и как она будет отформатирована.

Пример использования класса Formatter:

import logging

# Создаем объект логгера
logger = logging.getLogger('my_logger')
logger.setLevel(logging.INFO)

# Создаем объект форматирования
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Создаем объект потока вывода
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)

# Добавляем поток вывода к логгеру
logger.addHandler(stream_handler)

# Логирование сообщений
logger.debug('Отладочное сообщение')
logger.info('Информационное сообщение')
logger.warning('Предупреждающее сообщение')
logger.error('Ошибка')
logger.critical('Критическая ошибка')

В данном примере мы создаем логгер с именем my_logger и устанавливаем уровень логирования INFO. Затем мы создаем объект форматирования Formatter, указывая нужный нам формат записей лога - в данном случае '%(asctime)s - %(name)s - %(levelname)s - %(message)s'.

После этого мы создаем объект потока вывода StreamHandler и устанавливаем для него созданный объект форматирования. Затем мы добавляем этот поток вывода к нашему логгеру с помощью метода addHandler().

В конечном итоге, при вызове методов логгера (debug(), info(), warning(), error(), critical()) записи логов будут выводиться на консоль в нужном формате, заранее указанном с помощью объекта Formatter.

Вывод программы:

2022-06-01 10:15:30,123 - my_logger - INFO - Информационное сообщение
2022-06-01 10:15:30,123 - my_logger - WARNING - Предупреждающее сообщение
2022-06-01 10:15:30,123 - my_logger - ERROR - Ошибка
2022-06-01 10:15:30,123 - my_logger - CRITICAL - Критическая ошибка

Логгирование на email с модулем logging в Python

В языке Python есть модуль logging, который предоставляет возможность логгирования (записи журнала) различных событий во время работы программы. Он позволяет сохранять информацию о происходящих событиях в различных местах, включая файлы, консоль, базы данных и даже отправлять уведомления на почту.

В этой статье мы рассмотрим, как настроить логгирование на email с помощью модуля logging. Давайте начнем с импорта необходимых модулей:

import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

Первым делом нам необходимо настроить объект logging в соответствии с нашими потребностями. Для этого мы можем воспользоваться функцией basicConfig(), указав необходимые параметры, такие как уровень логирования (level) и формат сообщения (format).

Добавим следующий код в начало нашей программы:

logging.basicConfig(filename='app.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

В данном примере мы настроили логгирование, чтобы записывать все сообщения в файл app.log с уровнем логирования DEBUG. Также мы задали формат вывода сообщения, который включает дату и время записи, уровень логирования и текст сообщения.

Теперь нам нужно создать функцию для отправки логов на email. Она будет принимать список адресов электронной почты, тему письма и текст сообщения. Эту функцию можно использовать внутри обработчика логов:

def send_email(emails, subject, message):
    smtp_server = 'mail.example.com'
    smtp_port = 587
    smtp_username = 'your@email.com'
    smtp_password = 'your_password'
    sender = 'your@email.com'

    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = ', '.join(emails)
    msg['Subject'] = subject

    msg.attach(MIMEText(message, 'plain'))

    server = smtplib.SMTP(smtp_server, smtp_port)
    server.starttls()
    server.login(smtp_username, smtp_password)
    server.send_message(msg)
    server.quit()

В этом примере мы создали функцию send_email, которая подключается к SMTP-серверу, отправляет пустое сообщение с указанными заголовками и содержимым.

Осталось только настроить обработчик логов для отправки сообщений на email. Для этого мы можем использовать класс logging.handlers.SMTPHandler:

smtp_handler = logging.handlers.SMTPHandler(mailhost='mail.example.com',
                                                  fromaddr='your@email.com',
                                                  toaddrs=['recipient@email.com'],
                                                  subject='Error',
                                                  credentials=('your@email.com', 'your_password'))
smtp_handler.setLevel(logging.ERROR)
logging.getLogger('').addHandler(smtp_handler)

В данном примере мы создали обработчик SMTPHandler, который будет отправлять сообщения об ошибках (ERROR уровень логирования). Указанные параметры mailhost, fromaddr, toaddrs, subject, credentials должны быть заменены на реальные значения.

Теперь каждый раз, когда будет сгенерировано сообщение с уровнем логирования ERROR, оно будет отправлено на указанный email адрес.

Полный пример кода:

import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging.handlers

# Настройка логгирования
logging.basicConfig(filename='app.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# Функция для отправки email
def send_email(emails, subject, message):
    smtp_server = 'mail.example.com'
    smtp_port = 587
    smtp_username = 'your@email.com'
    smtp_password = 'your_password'
    sender = 'your@email.com'

    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = ', '.join(emails)
    msg['Subject'] = subject

    msg.attach(MIMEText(message, 'plain'))

    server = smtplib.SMTP(smtp_server, smtp_port)
    server.starttls()
    server.login(smtp_username, smtp_password)
    server.send_message(msg)
    server.quit()

# Настройка обработчика логов для отправки email
smtp_handler = logging.handlers.SMTPHandler(mailhost='mail.example.com',
                                            fromaddr='your@email.com',
                                            toaddrs=['recipient@email.com'],
                                            subject='Error',
                                            credentials=('your@email.com', 'your_password'))
smtp_handler.setLevel(logging.ERROR)
logging.getLogger('').addHandler(smtp_handler)

# Пример использования логгирования
logging.debug('Отладочное сообщение')
logging.info('Информационное сообщение')
logging.warning('Предупреждающее сообщение')
logging.error('Ошибка')
logging.critical('Критическая ошибка')

Логирование в Telegram с использованием модуля logging в Python

В этой абзаце мы рассмотрим пример логирования в Telegram с помощью модуля logging и пользовательского обработчика, унаследованного от logging.Handler. Для этого мы будем использовать библиотеку requests для взаимодействия с API Telegram.

Прежде чем приступить к примеру, убедитесь, что у вас установлены модуль requests и настроены необходимые доступы для работы с API Telegram.

Установка необходимых модулей

Предполагается, что у вас уже установлен Python на вашей системе. Чтобы начать использовать модуль logging и отправлять логи в Telegram, вам также понадобятся следующие модули:

  • requests - для отправки HTTP-запросов

Вы можете установить модули с помощью команды pip, выполнив следующие команды в командной строке:

pip install requests

Для начала создадим пользовательский обработчик TelegramHandler, который будет отправлять логи в Telegram. Для этого нам понадобится получить токен бота и идентификатор чата в Telegram:


import logging
import requests

class TelegramHandler(logging.Handler):
    def __init__(self, token, chat_id):
        super().__init__()
        self.token = token
        self.chat_id = chat_id

    def emit(self, record):
        log_entry = self.format(record)
        url = f"https://api.telegram.org/bot{self.token}/sendMessage"
        params = {
            "chat_id": self.chat_id,
            "text": log_entry
        }
        response = requests.get(url, params=params)
        if response.status_code != 200:
            raise ValueError("Failed to send log entry to Telegram")

        self.close()

В приведенном коде мы создаем класс TelegramHandler, унаследованный от logging.Handler. В конструкторе класса мы принимаем токен бота token и идентификатор чата chat_id, которые будут использоваться для отправки логов.

В методе emit() класса мы форматируем запись лога с помощью метода self.format(record) и отправляем ее через API Telegram с помощью библиотеки requests. Если возникает ошибка при отправке, мы выбрасываем исключение.

Теперь создадим и настроим логгер с использованием нашего обработчика:


# Устанавливаем уровень логирования
logging.basicConfig(level=logging.WARNING)

# Создаем логгер
logger = logging.getLogger(__name__)

# Создаем обработчик TelegramHandler
telegram_handler = TelegramHandler("YOUR_BOT_TOKEN", "YOUR_CHAT_ID")

# Устанавливаем уровень логирования для обработчика
telegram_handler.setLevel(logging.ERROR)

# Создаем форматировщик и устанавливаем его для обработчика
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
telegram_handler.setFormatter(formatter)

# Добавляем обработчик в логгер
logger.addHandler(telegram_handler)

# Пример записи логов
logger.error("This is an error message")
logger.warning("This is a warning message")

В приведенном примере мы настраиваем логгер таким образом, чтобы он записывал только сообщения с уровнем ERROR и более высоким. Мы также создаем форматировщик с помощью класса logging.Formatter и указываем его для нашего обработчика с помощью метода setFormatter().

Для отправки логов в Telegram мы создаем экземпляр TelegramHandler с указанием токена бота и идентификатора чата. Затем мы устанавливаем его уровень логирования и добавляем в логгер с помощью метода addHandler().

В результате при вызове методов logger.error() и logger.warning() логи будут отправлены в Telegram.