Логирование в Python. Модуль logging. Часть 1

Логирование в Python. Модуль logging. Часть 1

moderator E7

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


1.Модуль Logging

Итак , для каких целей нам нужен этот модуль:

  1. Форматирование логов
  2. Фильтрация логов
  3. Отправка логов в разные цели

Большинство людей не знают, что писать в логи, поэтому решают логировать все, что угодно, думая, что все подряд – это в любом случае лучше, чем ничего, и, в конечном итоге, просто создают шум. А шум – это информация, которая никак не помогает вашей команде понять, в чем дело и как решить проблему.

Цель статьи - решить данную проблему и объяснить на практических примерах как работает логирование.

Теперь перейдем к практике:

Для начала добавим модуль logging в нашу программу на Python , сделать это довольно просто :


import logging

С импортированным модулем logging вы можете использовать то, что называется «logger», для логирования сообщений, которые вы хотите видеть. По умолчанию существует 5 стандартных уровней severity, указывающих на важность событий. У каждого есть соответствующий метод, который можно использовать для логирования событий на выбранном уровне severity. Список уровней в порядке увеличения важности:

  1. DEBUG(10)
  2. INFO(20)
  3. WARNING(30)
  4. ERROR(40)
  5. CRITICAL(50)

Модуль 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')


WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message

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

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

2.Форматирование логов

Базовая конфигурация

Этот метод модуля logging мы будем использовать для конфигурации логов:

basicConfig(**kwargs)
Если вы внимательный читатель , вы могли заметить что метод написан в стиле camelCase , а не в snake_case как по правилам PEP8. Все это из-за того , что пакет был адаптирован из другого ЯП . Этим языком является Java , а адаптированная утилита - Log4j

У метода есть следующие параметры:

  • level: Корневой логер с установленным указанным уровнем важности (severity).
  • filename: Указание файла логов
  • filemode: Режим открытия файла. По умолчанию это a, что означает добавление.
  • format: Формат сообщений.

Это основные параметры . Разберем каждый по порядку:

Используя параметр level, вы можете установить, какой уровень сообщений журнала вы хотите записать. Это можно сделать, передав одну из констант, доступных в классе, и это позволило бы регистрировать все вызовы logging на этом уровне или выше. Вот пример:


import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug('This will get logged')


DEBUG:root:This will get logged

Теперь будут регистрироваться все события на уровне DEBUG или выше.


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

import logging

logging.basicConfig(filename='app.log', filemode='w', 
                    format='%(name)s - %(levelname)s - %(message)s')
logging.warning('This will get logged to a file')


root - ERROR - This will get logged to a file

Сообщение будет записано в файл с именем app.log вместо вывода в консоль. Для filemode значение w означает, что файл журнала открывается в «режиме записи» каждый раз, когда вызывается basicConfig(), и при каждом запуске программы файл перезаписывается. Конфигурацией по умолчанию для filemode является a, которое является добавлением.

Вы можете настроить корневой logger еще больше, используя дополнительные параметры для basicConfig(), которые можно найти в конце статьи.

Следует отметить, что вызов basicConfig() для настройки корневого logger работает, только если корневой logger не был настроен ранее. По сути, эта функция может быть вызвана только один раз.

debug(), info(), warning(), error() и crit() также автоматически вызывают basicConfig() без аргументов, если он ранее не вызывался.

Это означает, что после первого вызова одной из вышеперечисленных функций вы больше не сможете изменить настройки корневого logger.

Формат вывода

В этом разделе разберем , как оформить все красиво и главное понятно для разработчиков.

Можно передавать любую переменную, которая может быть представлена в виде строки из вашей программы в виде сообщения в ваши журналы, есть некоторые базовые элементы, которые уже являются частью LogRecord (такие как в примере - process , levelname и message) и могут быть легко добавлены в выходной формат.

Если вы хотите записать идентификатор процесса ID вместе с уровнем и сообщением, вы можете сделать что-то вроде этого:

import logging

logging.basicConfig(format='%(process)d-%(levelname)s-%(message)s')
logging.warning('This is a Warning')


18472-WARNING-This is a Warning


Можно добавить время создания логов с помощью %(asctime)s .

Формат можно изменить с помощью атрибута datefmt, который использует тот же язык форматирования, что и функции форматирования в модуле datetime, например time.strftime():


import logging

logging.basicConfig(format='%(asctime)s - %(message)s', 
                    datefmt='%d-%b-%y %H:%M:%S')
logging.warning('Admin logged out')


24-Aug-22 20:53:19 - Admin logged out

Вы можете найти больше информации о формате datetime в руководстве в конце статьи.

3.Заключение

На этом закончим первую часть статьи , а в следующей продолжим с:

Логирование переменных
Вывод стека
Свой класс logger

И многое другое , что позволит полностью познать логирование в Python


По всем вопросам пишите в комментарии , вам с радостью ответят ;)

С любовью от #E7TEAM


Ссылки на доп. материалы:

  1. доки для полной настройки конфигурации логов - basicConfig()
  2. доки со всеми атрибутами объекта - LogRecord
  3. руководство по формату - datetime

Report Page