Отладка кода на Python с помощью icecream



Книга Отладка кода на Python с помощью icecream

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


Конечно, не существует альтернативы, способной полностью заменить функцию print(). Однако для вывода отладочных сообщений в консоль лучше использовать другие инструменты. Например, в статье представлена интересная сторонняя библиотека Python под названием “IceCream”: с её помощью вы откроете для себя множество удобств быстрой и простой отладки программного кода.


Плохой пример



JavaMentor


JavaMentor

Начнем с относительно плохого примера. Предположим, что определена функция 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!


717   0  

Comments

    Ничего не найдено.