Не слушай профи - делай print()



Книга Не слушай профи - делай print()

Если вы скажете профессиональным программистам, что используете print() для отслеживания ошибок, готовьтесь уворачиваться от летящих в вашу сторону стульев. Есть ли смысл продираться через дебри трассировки стека с полной настройкой отладки, будучи новичком? Некоторые скажут “да”, поскольку они изначально научились это делать. Я же утверждаю: “Любые средства хороши  —  был бы результат”. 


Это совсем не значит, что вам не нужно учиться распознавать ошибки  —  речь о другом. Когда вы программируете в свое удовольствие или намереваетесь создать для кого-либо небольшие фрагменты кода, так ли необходимо проводить отладку на профессиональном уровне? Если вы занимаетесь программированием себе на радость и в свободное время, то вряд ли вам потребуется проводить “образцовую” отладку на протяжении всей вашей карьеры разработчика. 


Print()  —  быть или не быть 


В большинстве случаев коду рано или поздно потребуется отладка. К счастью, существует несколько способов ее осуществить, не прибегая к полному каноническому варианту разработчика.  


Прежде всего посмотрим, как функция print() может помочь в отладке кода. 


print()


print() обеспечит мгновенное визуальное воплощение того, над чем вы работаете. Если вы ожидаете вполне определенный результат, то сразу же увидите его в терминале. Если он верный  —  смело продолжайте работу. Если нет  —  ищите причину. 


Рассмотрим пример с применением print():


greek_gods = ['Zeus','Poseidon','Apollo','Bob']
greek_gods_only = [god for god in greek_gods if god!='Bob']
gods = ','.join(greek_gods_only)

Как узнать, удалось ли изгнать Боба (Bob) из стана богов? 


print(gods)

Боб покинул Олимп 

А теперь, когда Боб вернулся с небес на землю, можно рассмотреть пример из реальной практики. 


Не так давно я разработал инструмент в Autodesk Maya для управления камерами. В анимационной сцене мне потребовалось составить список всех камер съемки, исключив камеры, используемые в этом редакторе по умолчанию. К счастью для нас, в Maya они уже определены (startupCamera = True), поэтому их легко найти. 


import maya.cmds as cmds

list_cameras = cmds.listCameras()
cam_list = [cam for cam in list_cameras if not cmds.camera(cam, q=True, startupCamera=True)]

for cam in cam_list:
print(cam)

Камеры съемки лица

Как видите, первые три позиции в списке по-прежнему занимают ненужные камеры из каких-то ссылочных файлов. Теперь, воочию столкнувшись с этой ошибкой, я могу ее устранить, добавив and ‘face’ not in cam:


Прекрасно! 

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


Вывод данных с помощью print бережет наши деньги! 


Альтернативные варианты отладки 


Итак, вы, несомненно, хотите узнать доступные вам альтернативы отладки. С удовольствием используя print, вы понимаете, что неплохо бы расширить диапазон возможностей и пополнить “оружием” свой арсенал.  


Рассмотрим ряд дополнительных способов отладки кода. Надеюсь, какой-нибудь из них придется вам по душе (или вы просто продолжите работать с print).


Python Tutor


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


Возьмем, к примеру, очень продвинутую функцию. Добавим код и кликнем на Visualize Execution (визуализация выполнения).



После этого вы сможете работать с кодом, переходя от одной строки к другой. Код находится с левой стороны, а вывод данных  —  справа. 


В следующем примере показан заключительный этап программы (шаг 9). В строке 4 происходит выполнение sum_input(10,10), и справа мы видим функцию и значение, которое она возвращает. 


Python Tutor  —  это быстрый и наглядный способ проверить код.

Assert


“Assert  —  это просто логическое выражение, которое проверяет, возвращают ли условия true или false. Если значение верно, то программа никак не реагирует и переходит к следующей строке кода. Однако, если оно ложно, то программа останавливается и выбрасывает ошибку” [Источник programiz].


Перед вами простой пример использования assert


def sum_input(input_a, input_b):
return input_a + input_b

assert sum_input(2,3) == 5
assert sum_input(2,3) != 5

AssertionError показывает, что 2+3 на самом деле равняется 5.

С помощью assert можно проверить, соответствует ли выполнение кода ожиданиям. В вышеуказанном примере вы ждете возврата значения 5, поэтому используете этот код, который возвращает True.


assert sum_input(2,3) == 5


А есть и такой код: 


assert sum_input(2,3) != 5


2 + 3 в результате всегда дает только 5, следовательно вы ожидаете ошибку, которую и получаете. Измените код следующим образом assert sum_input(2,3) != 6 или укажите любое число кроме 5, и у вас не будет ошибок. 


Поскольку именно вы инициируете эти ошибки, то их отсутствие было бы странным. Хотите почистить код  —  воспользуйтесь вот этим вариантом: 


def sum_input(input_a, input_b):
return input_a + input_bassert sum_input(2,3) == 5
assert sum_input(2,3) != 6

Сам Усейн Болт мог бы позавидовать скорости выполнения программы

Можете создать свои собственные сообщения об ошибках:


assert sum_input(2,3) != 5, '2+3 is 5...Stop this nonsense'

Thonny


Не так давно состоялось мое первое знакомство с Thonny, и она не оставила мне выбора  —  я влюбился. Это простая IDE со встроенным отладчиком, который показывает все, что происходит в коде. Среда на удивление простая, а возможности отладки превосходят все ожидания. 


Рассмотрим следующий пример кода: программа проверяет все файлы, находящиеся в той же папке, что и программа Python. Затем она возвращает список с кортежем: (‘filename’, ‘extension’).


import os
import pathlib

def get_file_exts(directory):
#перечисляет все файлы в директории
search_path = pathlib.Path(directory).iterdir()
file_list = [file.name for file in search_path if file.is_file()]

#создает новый список с кортежем, включающем имена и расширения всех файлов:
file_ext = [os.path.splitext(file) for file in file_list]
return file_ext


def main():
#где находится файл:
current_dir = os.path.dirname(os.path.realpath(__file__))

#вызывает функцию для получения имен файлов и расширений, затем выводит данные.
for file in get_file_exts(current_dir):
print(file)


if __name__ == '__main__':
main()

Thonny проинформирует вас о том, всё ли в порядке с вашим кодом. Ниже мы видим выполнение этого кода и возвращаемые им результаты: 


Редактор кода, оболочка, помощник

Успешный возврат имен файлов и расширений в папку 

Если намеренно добавить ошибку, например переименовать search_path в searchc_path, то среагирует Помощник: 


Клик по ссылке в строке 8 в Помощнике выделяет ошибку 

Помощник также снабжает нас подсказками, облегчая процесс поиска и устранения ошибок. Если мы развернем вопрос “Did you misspell it (somewhere)?”, в котором он интересуется, а правильно ли было написано имя, то Thonny покажет нам похожие варианты имен и станет очевидно, где была допущена ошибка. 


Благодарю тебя, Помощник. Теперь я знаю, где ошибка. 

Если вы запускаете режим отладки, то Thonny пошагово выполнит код и покажет все, что в нем происходит: 


Режим отладки

Он останавливается на строке 24 с инструкцией if.


Выделение области

Позволяет нам узнать условие инструкции if 

Обратим внимание на __name__

Это ‘__main__’? 



Они совпадают? 

Да. Выполняем main()

pdb  —  встроенный отладчик Python 


Если же вы предпочитаете работать в терминале, то Python оснащен встроенным отладчиком, известным как pdb. Благодаря ему вам не приходится повсюду в коде применять функции print(). Помимо этого, вы можете проверять функции и переменные и тестировать код в реальном режиме без редактирования его исходного варианта. Используя данный способ отладки, вы не ломаете код только из-за необходимости протестировать те или иные случаи. 


Просто добавив в код breakpoint(), вы укажите интерпретатору, где именно вы намерены войти в режим отладки. Если у вас отсутствует новая версия Python (3.X), то придется внести дополнительную строку import pdb; pdb.set_trace().


Более подробную информацию о pdb вы найдете в соответствующей документации


Real Python также предоставляет полезный обучающий материал о возможностях отладчика. 


Заключение


Функция print() не заменит качественную отладку. Этот способ не приемлем для командной разработки, но вполне может подойти начинающим программистам. И почитателей print() гораздо больше, чем мы думаем. Во-первых, она ускоряет процесс отладки; во-вторых, вы узнаёте, каким должен быть ожидаемый результат; в-третьих, она моментально предоставляет наглядную информацию.


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


Если же вы намерены и дальше использовать print()  —  я только “за”. Главное, чтобы сеньоры были не против. 




602   0  

Comments

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