Рубрики
Без рубрики

Основы ведения журнала Python

Автор оригинала: Guest Contributor.

Вступление

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

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

Модуль ведения журнала

Модуль logging по умолчанию легко доступен в средах Python и предоставляет регистратор по умолчанию с именем “root”. Он определяет функции и классы, реализующие функции ведения журнала.

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

Типы журналов (Уровни журналов)

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

  • Debug ( logger.debug ): Предоставьте очень подробный вывод. Используется для диагностики проблем.

  • Информация ( logger.info ): Предоставляет информацию об успешном выполнении. Подтверждает, что все работает так, как ожидалось.

  • Предупреждение ( logger.предупредить или регистратор.предупреждение ): Выдайте предупреждение о проблеме, которая может возникнуть в будущем, или о неисправности, которую можно восстановить.

  • Error ( logger.error ): Указывает на проблему в программном обеспечении, поскольку оно выполняется не так, как ожидалось.

  • Critical ( logger.critical ): Указывает на серьезную ошибку, которая может остановить работу программы.

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

Чтобы добавить ведение журнала в скрипт Python, просто импортируйте модуль с помощью import logging , и после успешного импорта скрипт может регистрировать сообщения с помощью методов logging.* , таких как logging.debug() .

Здесь вы можете увидеть простой пример модуля ведения журнала в действии:

import logging
logging.warning("Caution: This is the root logger!")

Выход:

WARNING:root:Caution: This is the root logger!

Объекты регистратора

Модуль logging позволяет пользователю создавать несколько объектов регистратора. Различные типы объектов регистратора могут быть использованы для получения детального контроля над тем, как различные части приложения Python регистрируют свои сообщения-например, основное приложение Python может использовать root logger, в то время как сторонние библиотеки, используемые в этом приложении, могут использовать свои собственные объекты регистратора со своими собственными конфигурациями.

Используя функции регистратора по умолчанию root , мы можем вызывать их напрямую, например, logging.debug() . Можно настроить свой собственный регистратор, создав объект класса Logger , и это может быть полезно, если ваше приложение имеет несколько модулей.

Давайте посмотрим на некоторые классы и функции в модуле logging . Основные классы и их функции заключаются в следующем:

  • Loggers – Предоставляет интерфейс, который использует приложение. Объекты этого класса используются непосредственно для вызова функций в приложении.

  • Обработчики – Отправляет сообщения журнала в соответствующее место в программном обеспечении, например в стандартную консоль вывода, файл, через HTTP или даже по электронной почте (через SMTP).

  • Фильтры – Дает мелкозернистый контроль над выбором записей журнала для отображения.

  • Форматеры – задает окончательный макет записей журнала, указывая атрибуты, которые должны содержать выходные данные.

Из них наиболее часто используются объекты класса Logger .

Чтобы создать новый регистратор, мы можем использовать метод logging.getLogger () . В следующем скрипте мы регистрируем ошибки с помощью регистратора root , а также нашего пользовательского регистратора my_logger .

import logging

my_logger = logging.getLogger("My Logger")
logging.error("Error: Root Log")
my_logger.error("Error: My Logger log")

Выход:

ERROR:root:Error: Root Log
ERROR:My Logger:Error: My Logger log

Каждое сообщение журнала будет не только указывать источник – объект регистратора, через который оно было зарегистрировано, – но и отображать сообщение, основанное на конфигурации этого объекта регистратора.

В следующих разделах мы рассмотрим различные параметры конфигурации объектов регистратора.

Запись в файл по сравнению со стандартным выводом

По умолчанию объекты регистратора выводят журналы на стандартный вывод. Вы можете использовать метод basic Config() для изменения этого и других параметров. Ниже приведен список параметров для метода basic Config :

  • уровень: Установите регистратору уровень серьезности. Любые сообщения ниже этого уровня серьезности не будут регистрироваться.
  • имя файла: Имя файла, в который записываются журналы.
  • режим файла: Режим, в котором должен быть открыт указанный файл, если таковой имеется.
  • формат: Задает формат сообщения журнала. Это строка с атрибутами LogRecord .

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

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

  1. Импортируйте модуль ведения журнала.
  2. Настройте регистратор с помощью метода basic Config
  3. Создание объекта регистратора.
  4. Установка порогового значения регистратора.
  5. Используйте методы ведения журнала.

Это можно лучше понять на примере:

# Filename: test_logger.py

import logging

# Create a logger object
logger = logging.getLogger()

# Configure logger
logging.basicConfig(filename="test.log", format='%(filename)s: %(message)s', filemode='w')

# Setting threshold level
logger.setLevel(logging.DEBUG)

# Use the logging methods
logger.debug("This is a debug message")
logger.info("For your info")
logger.warning("This is a warning message")
logger.error("This is an error message")
logger.critical("This is a critical message")

Приведенный выше скрипт создаст файл “test.log”. Файл будет содержать следующую информацию журнала:

test_logger.py: This is a debug message
test_logger.py: For your info
test_logger.py: This is a warning message
test_logger.py: This is an error message
test_logger.py: This is a critical message

Дата/время в сообщениях журнала

Для отображения даты и времени наступления события можно использовать %(asctime)s в строке формата в функции basic Config () . Например:

import logging

logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is the time the Admin logged out.')

Выход:

2018-12-17 10:52:15,463 is the time the Admin logged out.

Если вы хотите изменить способ отображения даты/времени, вы можете настроить его с помощью параметра datefmt метода basic Config .

Переменные журнала

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

Вот пример этого с использованием форматирования строк:

import logging

status = "connection unavailable"
logging.error("System reported: %s", status)

Выход:

ERROR:root:System reported: connection unavailable

Начиная с Python 3.6 f-Strings можно использовать в качестве альтернативы спецификаторам строкового формата, тем самым сохраняя код легко читаемым при наличии нескольких параметров. Используя f-строки, вы можете указать любое выражение Python как часть сообщения, и они будут вычислены во время выполнения, а результат будет встроен в сообщения журнала.

Приведенный выше пример можно переписать с помощью f-строки следующим образом:

import logging

status = "connection unavailable"
logging.error(f'System reported: {status}')

Трассировки стека журналов

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

import logging

my_list = [1, 2]
try:
    print(my_list[3]) # Index out of range
except Exception as e:
    logging.error("Caught Exception!", exc_info=True)

Выход:

ERROR:root:Caught Exception!
Traceback (most recent call last):
  File "index.py", line 5, in 
    print(my_list[3]) # Index out of range
IndexError: list index out of range

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

Если стек не имеет обрабатываемых исключений, возвращается кортеж, имеющий значение None . В противном случае функция возвращает значение type (тип обрабатываемого исключения), value (параметр исключения) и traceback (объект traceback, инкапсулирующий стек вызовов, в котором первоначально возникло исключение).

Вывод

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