Модуль Logging является частью стандартной библиотеки в Python и обеспечивает отслеживание событий, которые происходят во время работы программы. Вы можете добавить протоколирование вызовов в коде, чтобы указать, какие события произошли.
Модуль Logging позволяет вести журнал диагностики, который регистрирует события, связанные с работой приложений, а также ведение журнала аудита, который регистрирует события операций пользователя для анализа. Особенно используется для записи событий в файл.
Модуль Logging хранит записи о событиях, которые происходят в рамках программы, что позволяет увидеть результат, связанный с каким – либо из событием, которое происходит во время выполнения части программного обеспечения.
Вы можете знакомы с проверкой, когда события происходят с помощью заявления print() на протяжении всего кода. Заявление print() обеспечивает основной способ отладки кода для решения проблем. В то время как вложения заявления print() по всему коду может отслеживать поток выполнения и текущее состояние программы, это решение оказывается хуже, чем при использовании модуля Logging по нескольким причинам:
Это хорошая идея, получить в привычку использовать модуль logging в коде, так как это больше подходит для приложений, прорастающих за пределы простых скриптов Python и обеспечивает устойчивый подход к отладке.
Поскольку журналы могут показать вам поведение и ошибки в течение долгого времени, они могут дать вам более полную картину того, что происходит в процессе разработки приложений.
Если вы привыкли использовать заявление print(), чтобы увидеть, что происходит в программе, вы может привыкли видеть программу, которая определяет класс и инициализирует объекты, которые выглядят примерно так:
class Pizza(): def __init__(self, name, price): self.name = name self.price = price print("Пицца создана: {} (${})".format(self.name, self.price)) def make(self, quantity=1): print("Изготовлена {} {} пицца(ы)".format(quantity, self.name)) def eat(self, quantity=1): print("Съели {} пиццу".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, который инициализируется как 1.
Теперь давайте запустим программу:
python pizza.py
Получим следующий результат:
Пицца создана: artichoke ($15) Изготовлена 1 artichoke пицца(ы) Съели 1 пиццу Пицца создана: margherita ($12) Изготовлена 2 margherita пицца(ы) Съели 1 пиццу
В то время как заявление print() позволяет нам видеть, как работает код, мы можем использовать модуль logging вместо него.
Давайте удалим или закомментируйте заявление print() в коде, и добавим import logging в начало файла:
import logging class Pizza(): def __init__(self, name, value): self.name = name self.value = value ...
Модуль logging имеет уровень WARNING по умолчанию, который является уровнем выше DEBUG. Так как мы будем использовать Модуль logging для отладки в данном примере, нам нужно изменить конфигурацию таким образом, чтобы был уровень logging был DEBUG, который будет возвращать информацию на консоль для нас. Мы можем сделать это, добавив следующую строку ниже оператора импорта:
import logging logging.basicConfig(level=logging.DEBUG) class Pizza(): ...
Уровень logging.DEBUG относится к постоянному целочисленному значению, мы ссылаемся в коде выше, чтобы установить порог. Уровень DEBUG10.
Теперь мы заменим все заявления print() на заявление logging.debug(). В отличие от константы logging.DEBUG которое является постоянным, logging.debug() является методом модуля logging. При работе с этим методом, мы можем использовать ту же строку, которая передается в print(), как показано ниже.
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("Изготовлена {} {} пицца(ы)".format(quantity, self.name)) def eat(self, quantity=1): logging.debug("Съели {} пиццу".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, мы получим следующий результат:
DEBUG:root:Пицца создана: artichoke ($15)
DEBUG:root:Изготовлена 1 artichoke пицца(ы)
DEBUG:root:Съели 1 пиццу
DEBUG:root:Пицца создана: margherita ($12)
DEBUG:root:Изготовлена 2 margherita пицца(ы)
DEBUG:root:Съели 1 пиццу
Сообщения журнала имеют уровень серьезности DEBUG, а также слова root встроенные в них, которое относится к уровню модуля Python. Модуль logging может быть использован с иерархией loggers, которое имеют разные названия, так что вы можете использовать другой регистратор для каждого из модулей.
Например, вы можете установить регистратор равный регистраторам, которые имеют разные названия и другой вывод:
logger1 = logging.getLogger("module_1") logger2 = logging.getLogger("module_2") logger1.debug("Module 1 debugger") logger2.debug("Module 2 debugger")
DEBUG:module_1:Module 1 debugger DEBUG:module_2:Module 2 debugger
Теперь, когда у нас есть понимание того, как использовать Модуль logging для печати сообщений на консоль, давайте перейдем к использованию модуля logging для вывода сообщений в файл.
Основная цель модуля logging состоит в выводе сообщений в файл, а не на консоль. Сохранение файла сообщений предоставляет данные в течение долгого времени, который вы можете оценить, так что вы можете увидеть, какие изменения были сделаны в вашем коде.
Для того, чтобы начать запись в файл, мы можем изменить logging.basicConfig() включив параметр filename. В этом случае, давайте назовем имя файла test.log:
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("Пицца создана: {} (${})".format(self.name, self.price)) def make(self, quantity=1): logging.debug("Изготовлена {} {} пицца(ы)".format(quantity, self.name)) def eat(self, quantity=1): logging.debug("Съели {} пиццу".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
Когда файл откроется, мы увидим следующее:
DEBUG:root:Пицца создана: artichoke ($15)
DEBUG:root:Изготовлена 1 artichoke пицца(ы)
DEBUG:root:Съели 1 пиццу
DEBUG:root:Пицца создана: margherita ($12)
DEBUG:root:Изготовлена 2 margherita пицца(ы)
DEBUG:root:Съели 1 пиццу
Это похоже на вывод консоли, с которым мы столкнулись в предыдущем разделе, только теперь он находится в файле test.log.
Давайте закроем файл с CTRL+ x и перейдем обратно в файл pizza.py, так что мы можем изменить код.
Мы изменим параметры в двух случаях пиццы, pizza_01 и pizza_02:
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("Пицца создана: {} (${})".format(self.name, self.price)) def make(self, quantity=1): logging.debug("Изготовлена {} {} пицца(ы)".format(quantity, self.name)) def eat(self, quantity=1): logging.debug("Съели {} пиццу".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
Когда мы посмотрим в файл, мы увидим, что были добавлены несколько новых линии, и что предыдущие строки из последнего времени, были сохранены:
DEBUG:root:Пицца создана: artichoke ($15) DEBUG:root:Изготовлена 1 artichoke пицца(ы) DEBUG:root:Съели 1 пиццу DEBUG:root:Пицца создана: margherita ($12) DEBUG:root:Изготовлена 2 margherita пицца(ы) DEBUG:root:Съели 1 пиццу DEBUG:root:Пицца создана: Sicilian ($18) DEBUG:root:Изготовлена 5 Sicilian пицца(ы) DEBUG:root:Съели 4 пиццу DEBUG:root:Пицца создана: quattro formaggi ($16) DEBUG:root:Изготовлена 2 quattro formaggi пицца(ы) DEBUG:root:Съели 2 пиццу
Хотя эта информация, безусловно, полезна, мы можем сделать журнал более информативным, добавив дополнительные атрибуты LogRecord. В первую очередь, мы хотели бы добавить удобочитаемый штамп времени, который говорит нам, когда LogRecord была создана.
Мы можем добавить атрибут параметра называемый format, ссылаться на него, как показано в таблице со строкой %(asctime)s. Кроме того, чтобы сохранить уровень DEBUG, нам нужно включить строку %(levelname)s и сохранить сообщение строки, которое зададим в logger распечатать %(message)s. Каждый из этих атрибутов будет разделен colon, как показано в коде добавленного ниже.
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("Пицца создана: {} (${})".format(self.name, self.price)) def make(self, quantity=1): logging.debug("Изготовлена {} {} пицца(ы)".format(quantity, self.name)) def eat(self, quantity=1): logging.debug("Съели {} пиццу".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 и связанным с ними сообщениями, которые передаются в регистратор как строки.
DEBUG:root:Пицца создана: Sicilian ($18) DEBUG:root:Изготовлена 5 Sicilian пицца(ы) DEBUG:root:Съели 4 пиццу DEBUG:root:Пицца создана: quattro formaggi ($16) DEBUG:root:Изготовлена 2 quattro formaggi пицца(ы) DEBUG:root:Съели 2 пиццу 2017-05-12 18:10:11,593:DEBUG:Пицца создана: Sicilian ($18) 2017-05-12 18:10:11,593:DEBUG:Изготовлена 5 Sicilian пицца(ы) 2017-05-12 18:10:11,593:DEBUG:Съели 4 пиццу 2017-05-12 18:10:11,593:DEBUG:Пицца создана: quattro formaggi ($16) 2017-05-12 18:10:11,593:DEBUG:Изготовлена 2 quattro formaggi пицца(ы) 2017-05-12 18:10:11,593:DEBUG:Съели 2 пиццу
В зависимости от ваших потребностей, вы можете использовать дополнительные атрибуты 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, так WARNING, ERROR и CRITICAL все будут регистрироваться по умолчанию. В приведенном выше примере, мы изменили конфигурацию, чтобы включать в себя уровень DEBUG со следующим кодом:
logging.basicConfig(level=logging.DEBUG)
Вы можете прочитать больше о командах и работе с отладчиком из официальной документации по модулю logging.
Отладка является важным шагом любого проекта разработки программного обеспечения. Модуль logging является частью стандартной библиотеки Python, обеспечивает отслеживание событий, которые происходят в то время как программа работает, и может выводить эти события в отдельный файл журнала, чтобы позволить Вам отслеживать то, что происходит в то время как ваш код работает. Это дает вам возможность отладки кода, основанного на понимании различных событий, которые происходят с запуском программы с течением времени.