Как использовать ведение журнала в Python 3

Вступление

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

loggingМодуль позволяет как журнал диагностики , который регистрирует события , связанные с работой приложений ‘, а также ведение журнала аудита , который регистрирует события операций пользователя для анализа. Он особенно используется для записи событий в файл.

Зачем использовать loggingмодуль

loggingМодуль хранит запись о событиях , которые происходят в рамках программы, что позволяет увидеть результат , связанный с каким — либо из событий , которые происходят во время выполнения части программного обеспечения.

Возможно, вы знакомы с проверкой того, что события происходят с использованием print()инструкции во всем коде. print()Заявление делает обеспечить основной способ идти о отладке кода для решения проблем. Несмотря на то, что вложения print()заявлений по всему вашему коду могут отслеживать поток выполнения и текущее состояние вашей программы, это решение оказывается менее ремонтопригодным, чем использование loggingмодуля по нескольким причинам:

  • Трудно различать вывод отладки и выход нормального программного обеспечения, поскольку эти два являются смешанными
  • При использовании print()операторов, распространяемых по всему коду, нет простого способа отключить те, которые обеспечивают вывод отладки
  • Сложно удалить все print()заявления, когда вы закончите с отладкой
  • Нет записи журнала, которая содержит легкодоступную диагностическую информацию

Это хорошая идея, чтобы привыкнуть использовать loggingмодуль в коде, поскольку это более подходит для приложений, которые выходят за рамки простых скриптов Python и обеспечивают устойчивый подход к отладке.

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

Печать отладочных сообщений на консоль

Если вы привыкли использовать print()оператор для просмотра того, что происходит в программе, вы можете использовать для просмотра программы, которая определяет класс, и создает объекты, которые выглядят примерно так:

pizza.py
class Pizza():
    def __init__(self, name, price):
        self.name = name
        self.price = price
        print("Pizza created: {} (${})".format(self.name, self.price))

    def make(self, quantity=1):
        print("Made {} {} pizza(s)".format(quantity, self.name))

    def eat(self, quantity=1):
        print("Ate {} pizza(s)".format(quantity, self.name))

pizza_01 = Pizza("artichoke", 15)
pizza_01.make()
pizza_01.eat()

pizza_02 = Pizza("margherita", 12)
pizza_02.make(2)
pizza_02.eat()

В приведенном выше коде есть __init__метод для определения объекта nameи priceобъекта Pizza. Тогда у него есть два метода, один призвал make()к созданию пиццы, а один призывал eat()есть пиццу. Эти два метода принимают параметр quantity, который инициализируется at 1.

Теперь давайте запустим программу:

  • python pizza.py

Мы получим следующий результат:

Output
Pizza created: artichoke ($15)
Made 1 artichoke pizza(s)
Ate 1 pizza(s)
Pizza created: margherita ($12)
Made 2 margherita pizza(s)
Ate 1 pizza(s)

Хотя print()оператор позволяет нам видеть, что код работает, мы можем использовать loggingмодуль, чтобы сделать это вместо этого.

Давайте удалим или прокомментируем print()инструкции по всему коду и добавим import loggingв начало файла:

pizza.py
import logging


class Pizza():
    def __init__(self, name, value):
        self.name = name
        self.value = value
...

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

pizza.py
import logging

logging.basicConfig(level=logging.DEBUG)


class Pizza():
...

Этот уровень logging.DEBUGотносится к постоянному целочисленному значению, которое мы ссылаемся в приведенном выше коде для установки порогового значения. Уровень DEBUGравен 10.

Теперь мы заменим все print()утверждения logging.debug()операторами. В отличие logging.DEBUGот константы, logging.debug()это метод loggingмодуля. При работе с этим методом мы можем использовать одну и ту же строку, переданную print(), как показано ниже.

pizza.py
import logging

logging.basicConfig(level=logging.DEBUG)


class Pizza():
    def __init__(self, name, price):
        self.name = name
        self.price = price
        logging.debug("Pizza created: {} (${})".format(self.name, self.price))

    def make(self, quantity=1):
        logging.debug("Made {} {} pizza(s)".format(quantity, self.name))

    def eat(self, quantity=1):
        logging.debug("Ate {} pizza(s)".format(quantity, self.name))

pizza_01 = Pizza("artichoke", 15)
pizza_01.make()
pizza_01.eat()

pizza_02 = Pizza("margherita", 12)
pizza_02.make(2)
pizza_02.eat()

На этом этапе, когда мы запускаем программу с помощью python pizza.pyкоманды, мы получим этот вывод:

Output
DEBUG:root:Pizza created: artichoke ($15)
DEBUG:root:Made 1 artichoke pizza(s)
DEBUG:root:Ate 1 pizza(s)
DEBUG:root:Pizza created: margherita ($12)
DEBUG:root:Made 2 margherita pizza(s)
DEBUG:root:Ate 1 pizza(s)

Сообщения журнала имеют уровень серьезности, DEBUGа также rootвстроенное в них слово , которое относится к уровню вашего модуля Python. loggingМодуль может быть использован с иерархией лесорубов , которые имеют разные названия, так что вы можете использовать другой регистратор для каждого из модулей.

Например, вы можете установить регистраторы равными различным регистраторам, которые имеют разные имена и разные выходные данные:

logger1 = logging.getLogger("module_1")
logger2 = logging.getLogger("module_2")

logger1.debug("Module 1 debugger")
logger2.debug("Module 2 debugger")
Output
DEBUG:module_1:Module 1 debugger
DEBUG:module_2:Module 2 debugger

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

Регистрация сообщений в файл

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

Чтобы начать регистрацию в файл, мы можем изменить logging.basicConfig()метод для включения filenameпараметра. В этом случае давайте назовем имя файла test.log:

pizza.py
import logging

logging.basicConfig(filename="test.log", level=logging.DEBUG)


class Pizza():
    def __init__(self, name, price):
        self.name = name
        self.price = price
        logging.debug("Pizza created: {} (${})".format(self.name, self.price))

    def make(self, quantity=1):
        logging.debug("Made {} {} pizza(s)".format(quantity, self.name))

    def eat(self, quantity=1):
        logging.debug("Ate {} pizza(s)".format(quantity, self.name))

pizza_01 = Pizza("artichoke", 15)
pizza_01.make()
pizza_01.eat()

pizza_02 = Pizza("margherita", 12)
pizza_02.make(2)
pizza_02.eat()

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

Давайте откроем test.logфайл с помощью nano (или текстового редактора по вашему выбору):

  • nano test.logКогда файл откроется, мы увидим следующее:
test.log
DEBUG:root:Pizza created: artichoke ($15)
DEBUG:root:Made 1 artichoke pizza(s)
DEBUG:root:Ate 1 pizza(s)
DEBUG:root:Pizza created: margherita ($12)
DEBUG:root:Made 2 margherita pizza(s)
DEBUG:root:Ate 1 pizza(s)

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

Давайте закроем файл с помощью CTRLxи вернемся в pizza.pyфайл, чтобы мы могли модифицировать код.

Мы будем хранить большую часть кода одинаково, но изменим параметры в двух экземплярах pizza pizza_01и pizza_02:

pizza.py
import logging

logging.basicConfig(filename="test.log", level=logging.DEBUG)


class Pizza():
    def __init__(self, name, price):
        self.name = name
        self.price = price
        logging.debug("Pizza created: {} (${})".format(self.name, self.price))

    def make(self, quantity=1):
        logging.debug("Made {} {} pizza(s)".format(quantity, self.name))

    def eat(self, quantity=1):
        logging.debug("Ate {} pizza(s)".format(quantity, self.name))

# Modify the parameters of the pizza_01 object
pizza_01 = Pizza("Sicilian", 18)
pizza_01.make(5)
pizza_01.eat(4)

# Modify the parameters of the pizza_02 object
pizza_02 = Pizza("quattro formaggi", 16)
pizza_02.make(2)
pizza_02.eat(2)

С этими изменениями, давайте снова запустить программу с помощью python pizza.pyкоманды.

Как только программа запустится, мы test.logснова сможем открыть наш файл с помощью nano:

  • nano test.log

Когда мы посмотрим на файл, мы увидим, что было добавлено несколько новых строк и что предыдущие строки с последнего запуска программы были сохранены:

test.log
DEBUG:root:Pizza created: artichoke ($15)
DEBUG:root:Made 1 artichoke pizza(s)
DEBUG:root:Ate 1 pizza(s)
DEBUG:root:Pizza created: margherita ($12)
DEBUG:root:Made 2 margherita pizza(s)
DEBUG:root:Ate 1 pizza(s)
DEBUG:root:Pizza created: Sicilian ($18)
DEBUG:root:Made 5 Sicilian pizza(s)
DEBUG:root:Ate 4 pizza(s)
DEBUG:root:Pizza created: quattro formaggi ($16)
DEBUG:root:Made 2 quattro formaggi pizza(s)
DEBUG:root:Ate 2 pizza(s)

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

Мы можем добавить этот атрибут к вызываемому параметру format, ссылаясь на него, как показано в таблице со строкой %(asctime)s. Кроме того, чтобы сохранить DEBUGимя уровня, нам нужно будет включить строку %(levelname)sи сохранить строковое сообщение, которое мы попросим распечатать в журнале, мы будем включать %(message)s. Каждый из этих атрибутов будет разделен символом a colon, как показано в приведенном ниже коде.

pizza.py
import logging

logging.basicConfig(
    filename="test.log",
    level=logging.DEBUG,
    format="%(asctime)s:%(levelname)s:%(message)s"
    )


class Pizza():
    def __init__(self, name, price):
        self.name = name
        self.price = price
        logging.debug("Pizza created: {} (${})".format(self.name, self.price))

    def make(self, quantity=1):
        logging.debug("Made {} {} pizza(s)".format(quantity, self.name))

    def eat(self, quantity=1):
        logging.debug("Ate {} pizza(s)".format(quantity, self.name))

pizza_01 = Pizza("Sicilian", 18)
pizza_01.make(5)
pizza_01.eat(4)

pizza_02 = Pizza("quattro formaggi", 16)
pizza_02.make(2)
pizza_02.eat(2)

Когда мы запускаем код выше с добавленными атрибутами с помощью python pizza.pyкоманды, мы добавим новые строки в наш test.logфайл, которые включают в себя человеко-читаемую метку времени в дополнение к имени уровня DEBUGи связанным с ним сообщениям, которые передаются в регистратор как строки.

Output
DEBUG:root:Pizza created: Sicilian ($18)
DEBUG:root:Made 5 Sicilian pizza(s)
DEBUG:root:Ate 4 pizza(s)
DEBUG:root:Pizza created: quattro formaggi ($16)
DEBUG:root:Made 2 quattro formaggi pizza(s)
DEBUG:root:Ate 2 pizza(s)
2017-05-01 16:28:54,593:DEBUG:Pizza created: Sicilian ($18)
2017-05-01 16:28:54,593:DEBUG:Made 5 Sicilian pizza(s)
2017-05-01 16:28:54,593:DEBUG:Ate 4 pizza(s)
2017-05-01 16:28:54,593:DEBUG:Pizza created: quattro formaggi ($16)
2017-05-01 16:28:54,593:DEBUG:Made 2 quattro formaggi pizza(s)
2017-05-01 16:28:54,593:DEBUG:Ate 2 pizza(s)

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

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

Таблица уровней ведения журнала

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

Уровни ведения журнала являются технически целыми числами (константа), и они все с шагом 10, начиная с NOTSETкоторого инициализирует регистратор при числовом значении 0.

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

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

уровень Числовое значение функция Использовал к
CRITICAL 50 logging.critical() Показать серьезную ошибку, программа может быть не в состоянии продолжить работу
ERROR 40 logging.error() Показать более серьезную проблему
WARNING 30 logging.warning() Укажите что-то неожиданное, или может случиться
INFO 20 logging.info() Подтвердите, что все работает как ожидается
DEBUG 10 logging.debug() Диагностировать проблемы, показать подробную информацию

loggingМодуль устанавливает уровень по умолчанию на WARNING, так WARNINGERRORи CRITICALвсе будет зарегистрирован по умолчанию. В приведенном выше примере мы изменили конфигурацию, чтобы включить DEBUGуровень с помощью следующего кода:

logging.basicConfig(level=logging.DEBUG)

Вы можете больше узнать о командах и работать с отладчиком из официальнойloggingдокументации .

Заключение

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *