Используем силу встроенных библиотек
Недавно мы разбирали, что такое логгеры, и подключали их к проектам на JavaScript. Смысл в том, чтобы научить наши программы отчитываться о своей работе, что упростит нам отладку.
Вот короткая версия того, что было в предыдущих частях:
- логгер — это специальный модуль или библиотека, которая фиксирует определённые события в нашей программе;
- на что реагировать и как фиксировать — решает программист;
- для этого он пишет специальную команду типа лог.добавить('Запускаем главный модуль') или лог.ошибка('Файл не найден');
- сам по себе лог ничего не исправляет — он только сообщает о том, что происходит в программе;
- есть несколько основных уровней логирования — ошибки, предупреждения, информационные сообщения, сообщения отладки и разовые события;
- эти уровни нужны для того, чтобы фильтровать сообщения по степени важности, например посмотреть только сообщения об ошибках или о штатных срабатываниях;
- лог можно выводить в консоль, в файл или передавать с помощью сокетов или API в другую программу;
- когда мы подключили логгер в наш проект с арканоидом на JavaScript, то неожиданно для себя нашли ошибку, которую без логгера мы не замечали.
Теперь поработаем с логгером в проекте на Python и посмотрим, найдём ли мы ещё ошибки в своём коде.
Настраиваем логгер
Python хорош тем, что с ним в комплекте идёт много полезных библиотек, в том числе логгер. Поэтому мы будем использовать встроенный логгер, который подключается так:
import logging
С этого момента мы можем использовать логгер в любом месте, просто указав нужный уровень сообщения, например:
Если запустить этот код, то мы увидим только последние два сообщения:
Дело в том, что логгер по умолчанию выводит только сообщения с уровнем warning и выше. Чтобы вывести все сообщения начиная с самого нижнего уровня debug, используем такую команду:
logging.basicConfig(level=logging.DEBUG)
Теперь все сообщения на месте:
Выводим сообщения в файл
По умолчанию логгер пишет всё в консоль, но можно отправлять все сообщения в файл. Для этого в настройках логгера укажем имя файла:
logging.basicConfig(level=logging.DEBUG, filename="thecode.log")
Файл появится в той же папке, что и программа, и мы сможем открыть его в любом текстовом редакторе:
Но при этом в консоли мы ничего не увидим — весь вывод ушёл в файл. Чтобы оставить сообщения в консоли и при этом добавлять их в файл, сделаем немного программистского колдунства — вручную настроим потоки вывода и объединим их в одно целое:
Теперь лог будет выводиться и в файл, и в консоль.
Добавляем логгер в проект
Смысл логгера — выводить сообщения в тех местах, где программисту нужна какая-то информация о том, как работает программа в этом месте. Нет смысла запихивать логгер после каждой строчки кода — получится огромный лог, в котором будет сложно разобраться.
Чтобы поработать с логгером на практике, достаточно любого, даже самого простого проекта на Python. Мы возьмём лёгкую задачу про безумного рекрутера на Python и добавим в неё лог — так будет проще понять, как всё работает. Если освоитесь с этим, то сможете подключить логгер в проект любой сложности — принцип будет точно такой же.
Мы добавим несколько логов
- информационные — на создание переменных;
- предупреждения — перед входом в каждый цикл (если мы зациклимся, то сразу будем знать, где именно);
- отладки — промежуточные значения переменной цикла.
Вот готовый код:
Когда мы запустим этот код, то увидим очень много сообщений в консоли. Это произошло потому, что мы выводим логи всех уровней — от отладочных до критических:
Так произошло из-за того, что мы указали уровень DEBUG в настройках логгера. Изменим их так, чтобы логгер нам их не показывал, а всё другое — оставил:
logging.basicConfig(handlers=(file_log, console_out), level=logging.INFO)
Вот так, управляя уровнем вывода логов, можно как детально погрузиться в ход работы программы, так и посмотреть всю работу без подробностей.