Источник: Nuances of Programming
Вопрос: какую из стандартных функций Python разработчики используют чаще всего? Наверняка, как и в большинстве языков программирования, ответом будет функция print(): во время разработки трудно удержаться от многократного вывода сообщений в консоль.
Конечно, не существует альтернативы, способной полностью заменить функцию print(). Однако для вывода отладочных сообщений в консоль лучше использовать другие инструменты. Например, в статье представлена интересная сторонняя библиотека Python под названием “IceCream”: с её помощью вы откроете для себя множество удобств быстрой и простой отладки программного кода.
Плохой пример
Начнем с относительно плохого примера. Предположим, что определена функция square_of, и мы хотим проверить, работает ли она согласно ожиданиям.
def square_of(num): return num*num
Вышеописанная функция банально возвращает квадрат числа, переданного в качестве аргумента. Проверим её пару раз:
print(square_of(2))
print(square_of(3))
print(square_of(4))
Пока функция одна, тем более такая простая, подобный подход к отладке программного кода удовлетворяет всем потребностям. Однако те функции, с чьей отладкой придется встретиться на практике, состоят из гораздо большего количества строк кода. Кроме того, часто встречается необходимость множественного вызова функции print() для абсолютно разных значений: в таком случае легко запутаться, какой вывод генерируется той или иной функцией print().
print('square of 2:', square_of(2))
print('square of 3:', square_of(3))
print('square of 4:', square_of(4))
Теперь пример стал немного лучше, но каждый раз вручную прописывать пояснительные строки — слишком утомительно. Более того, после окончания разработки, скорее всего, вам придется удалить почти все отладочные сообщения.
Проверка переменных
Обратим внимание на Python-библиотеку под названием “Ice Cream” и ответим на вопрос: как она решает проблемы, о которых говорилось выше?
Прежде всего, необходимо установить библиотеку из репозитория PyPI с помощью пакетного менеджера pip (или любого другого):
pip install icecream
Перед использованием библиотеки — импортируем её в программу:
from icecream import ic
Вследствие чего появляется возможность гораздо удобнее выводить отладочную информацию в консоль.
Вызов функции
Библиотеку icecream можно использовать напрямую для вывода возвращаемых функцией значений в консоль, точно так же, как ранее использовалась функция print().
ic(square_of(2))
ic(square_of(3))
ic(square_of(4))
Отлично! Несмотря на то, что не указано ни одного отладочного сообщения для вызова функции ic(), она все равно выводит на экран имя функции, ее аргументы и результат выполнения. Таким образом, нам больше не нужно вручную добавлять “краткое описание”.
Доступ к словарю
Кроме обычного вызова функции, похожего на print(), библиотека icecream способна выводить всю необходимую информацию в удобном для чтения виде, ускоряя и облегчая отладку, например при обращении к паре ключ-значение в словаре.
my_dict = {
'name': 'Chris',
'age': 33 }
ic(my_dict['name'])
В примере определен словарь, и необходимо реализовать доступ к его значению по ключу. При использовании библиотеки icecream в консоль выводится и значение словаря, и ключ, к которому выполнялось обращение.
Доступ к атрибутам объекта
В качестве еще одного примера, давайте определим класс и создадим для него объект-экземпляр:
class Dog(): num_legs = 4 tail = True
dog = Dog()
Вывод в консоль значения атрибута объекта-экземпляра класса Dog с помощью библиотеки icecream:
ic(dog.tail)
Отладка условия if
Библиотека icecream упрощает проверку не только переменных, но и управляющих конструкций, таких как условие if. Например, рассмотрим простое условие:
input = 'Chris'
if input == 'Chris':
ic()
else:
ic()
Для начала разместим вызов функции icecream в блоках if и else. Посмотрим, что произойдет:
Хотя в коде программы оператор условия if-else буквально ничего не делает, функция ic() выводит в консоль номер строки, где она была вызвана, и время вызова.
Пример демонстрируется в Jupyter Notebook, но при запуске функции ic() из файла в формате .py, кроме номера строки и времени запуска вы также получите имя файла, из которого произошел вызов.
Рассмотрим более практичный случай использования функции ic() из Python-библиотеки icecream:
def check_user(username): if username == 'Chris':
# Делается что-либо ic()
else:
# Делается что-либо еще ic()
check_user('Chris')
check_user('Jade')
При вызове функция check_user() подействует в зависимости от значения аргумента username. Допустим, в целях отладки важно знать, кто именно является текущим пользователем. Функция ic() как раз сообщает нам это:
Вставка в существующий код
Далее обсудим одну интересную особенность библиотеки icecream: функция ic() не только выводит подробную информацию в консоль, но и передает значение таким образом, что оно может использоваться в качестве функции-обертки для всего что угодно. Другими словами, функция ic() способна обернуть в себя любой объект, не затрагивая создавая последствий.
Давайте рассмотрим новый функционал библиотеки icecream на примере все той же функции sqaure_of(), определенной в предыдущем разделе статьи.
num = 2
square_of_num = square_of(ic(num))
В примере определена переменная num, и нам нужно вычислить ее квадрат с помощью вызова функции square_of(). Вместо square_of(num) в примере выше функция ic() оборачивает саму переменную num. Таким образом, консольный вывод будет состоять не из результата работы функции square_of(num), присвоенного переменной square_of_num, а только из значения самой переменной num.
А вот протестировать результат из переменной square_of_num можно следующим образом:
Как видно, square_of_num равна квадрату переменной num. Кроме того, в данном if-условии не только функция ic() используется без влияния на результат, но и переменная square_of_num все равно выводится для отладки!
Отключение библиотеки icecream
Одна из больших проблем использования функции print() в отладочных целях заключается в том, что сообщений слишком много. Кроме того, они часто остаются повсюду после завершения разработки. В таком случае желание быстро очистить код от отладочных сообщений, написанных с помощью функции print(), приведет к настоящей катастрофе.
А вот в случае использования отладочной библиотеки icecream, все, что нам нужно сделать, — это просто отключить ее!
ic.disable()
После выполнения метода ic.disable() все функции ic(), из любого места в коде программы, перестанут что-либо выводить в консоль. Например, приведенный ниже код ничего не выведет:
Тем не менее следует задаться вопросом: как насчет переменной square_of_num? Будет ли она по-прежнему передаваться после отключения библиотеки icecream? Не волнуйтесь, ic.disable() отключает исключительно вывод текста в консоль, не нужно беспокоиться о работоспособности обернутых в ic() функций.
if ic(square_of_num) == pow(num, 2):
print('Correct!')
При замене консольного вывода обратно на функцию print(), программа все равно будет работать. Получается, что ic(square_of_num) по-прежнему эквивалентно square_of_num:
Конечно, снова понадобится вернуться в режим отладки, icecream очень легко включается обратно:
ic.enable()
Настройка отладочных сообщений
Библиотека icecream реализовывает тонкую настройку и форматирование сообщений. Самой популярной настройкой считается изменение префикса. Вы, наверное, заметили, что вывод отладочных сообщений по умолчанию всегда начинается с префикса ic |. Это можно изменить.
Например, ввиду отладочной цели хорошей идеей будет указать слово Debug в качестве префикса:
ic.configureOutput(prefix='Debug | ')
ic('test')
Более того, в качестве префикса можно указывать не только статические строки, но и функции. Например, определим функцию, возвращаемое значение которой является текущей временной меткой в виде форматированной строки.
from datetime import datetime
def now(): return f'[{datetime.now()}] '
Затем установим полученную функцию now() в качестве префикса отладочных сообщений icecream:
ic.configureOutput(prefix=now)
ic('test')
Выводы
В статье представлена замечательная сторонняя Python-библиотека под названием “Ice Cream”. Она улучшает функцию print(), детализируя ее и повышая удобство отладки программ на Python.
Библиотека icecream никогда не заменит стандартную функцию print(), потому что у них разные цели, а также систему протоколирования. Она скорее находится где-то между этими двумя инструментами.
Жизнь коротка, используйте Python!
Читайте также:
Перевод статьи Christopher Tao: Do Not Use Print For Debugging In Python Anymore