Даже у самых опытных разработчиков код редко работает идеально с первого раза. Но чем опытнее разработчик, тем лучше он отлаживает код, то есть анализирует ошибки и устраняет их.
Навык отладки сам по себе не появится: его необходимо развивать, причем начинать нужно как можно раньше. По ходу обучения вы будете выполнять задания и практиковаться — все это поможет набраться опыта. Со временем анализ и устранение ошибок войдут в привычку, если уделять достаточно внимания практике.
Как найти ошибку в коде
Можно отлаживать некорректно работающий код методом тыка, но это долго и непродуктивно. Будет намного проще, если вы сначала поймете проблему, а уже потом начнете устранять ее. Понимание — это ключевой этап, без которого дальнейшие шаги невозможны.
Перед отладкой кода надо понять, что в нем не так. Это можно сделать за два шага.
Шаг 1. Изучить трейсбек (traceback) — список всех вызовов функций от запуска программы до места с ошибкой. Трейсбек помогает отследить, как прошло выполнение программы: какие функции получилось вызвать успешно, а с какими — возникли сложности. Каждая запись в трейсбеке указывает на файл и строчку, а затем на выполняемую функцию.
Представим, что вы написали код в файле users.py
и решили запустить функцию main()
в четвертой строчке. Запись в трейсбеке будет выглядеть так:
File "users.py", line 4, in <module>
main()
Как видите, здесь указаны не только файл и строчка, но еще и название модуля. По нему можно с легкостью определить, где возникла проблема: в вашем коде или в какой-то библиотеке, которую вы не писали, но используете.
Шаг 2. Когда трейсбек дойдет до проблемного места, он выдаст сообщение об ошибке. Например, такое:
NameError: name 'create' is not defined
Если владеете английским, то быстрее поймете, о чем идет речь в сообщении: «Название create
не определено». Эта ошибка чаще всего происходит из-за опечатки в названии — нужно проверить этот момент. Без знания английского тоже можно разобраться, если обратиться к словарю или онлайн-переводчику.
Теперь посмотрим, как трейсбек и сообщение об ошибке выглядят вместе:
Traceback (most recent call last):
File "users.py", line 4, in <module>
main()
File "users.py", line 2, in main
create()
NameError: name 'create' is not defined
В примере выше видно всю цепочку событий: программа успешно справилась с функцией main()
, а потом перешла к функции create()
и столкнулась с ошибкой в названии.
Кроме NameError, в Python есть еще множество разных ошибок, которые можно разделить на три группы.
Типы ошибок
Самые простые и понятные ошибки — синтаксические. Они связаны исключительно с тем, что код неверно оформлен: например, использованы неправильные кавычки.
В выводе таких ошибок всегда присутствует фраза SyntaxError:
. Чтобы отладить код в этом случае, нужно внимательно взглянуть на место с ошибкой. Посмотрим на примере. Здесь синтаксическая ошибка произошла потому, что использована кавычка '
вместо "
:
Traceback (most recent call last):
File "users.py", line 2
print("Hello" + "world')
^
SyntaxError: EOL while scanning string literal
Вторая большая группа ошибок — это ошибки программирования. Например, к ним относятся:
- Вызов несуществующей функции
- Использование необъявленной переменной
- Передача неверных аргументов (например, аргументов неверного типа)
Эти ошибки исправить труднее, чем синтаксические. Обычно они возникают, если в другом более раннем вызове была неправильная логика.
Последний тип ошибок — логические ошибки. Исправить ситуацию бывает очень сложно, потому что программа в целом работает, но при некоторых значениях выдает неверный результат. В большинстве случаев проблема кроется в неверной логике. Например, вместо сложения в программе выполняется вычитание:
# Функция должна считать сумму чисел, но считает разность:
def sum(a: int, b: int) -> int:
return a - b
# При таком вызове ошибка неочевидна, потому что
# и при сложении, и при вычитании будет один и тот же результат
sum(4, 0) # 4
Способы отладки
Есть множество способов отладки программ, но у всех одна общая идея — нужно проанализировать, как меняются значения переменных в процессе работы кода.
Рассмотрим на конкретном примере. Ниже описана функция, которая считает сумму чисел от числа start
до числа finish
. Если start
равно трём, а finish
— пяти, то программа должна вычислить: 3 + 4 + 5
.
def sum_of_series(start: int, finish: int) -> int:
result = 0
n = start
while n < finish:
result = result + n
n = n + 1
return result
В этом коде допущена ошибка. Глядя на код функции sum_of_series()
, замечаем, что основных переменных там две: n
и result
. Из этого можно сделать такой вывод — нужно посмотреть, какие значения даются переменным на каждой итерации. После этого найти ошибку не составит труда.
Есть удобный инструмент для отслеживания значений переменных во время выполнения кода — это визуальные отладчики. Они встраиваются в популярные редакторы кода и позволяют выполнить программу по шагам и увидеть все изменения. Если интересно узнать больше об отладчиках, можно поискать в Google по запросу Python debuggers.
В среде Хекслета отладчика нет, поэтому здесь используется другой подход — отладочная печать. Принцип работы такой же, как и в визуальном отладчике. Разница только в том, что для вывода значений переменных используется обычная печать на экране. То, что печатается на экране, отображается во вкладке OUTPUT
, на которую автоматически переключается редактор во время проверки. Посмотрим на примере:
def sum_of_series(start: int, finish: int) -> int:
result = 0
n = start
while n < finish:
print("new iteration !!!!")
print(n)
result = result + n
n = n + 1
print(result)
return result
sum_of_series(3, 5)
# new iteration !!!!
# 3
# 3
# new iteration !!!!
# 4
# 7
Здесь видно, что итераций цикла на одну меньше, чем нужно. Почему-то не выполняется сложение для последнего числа, которое обозначено как finish
. И действительно, если посмотреть на определение, то видно, что там используется n < finish
вместо n <= finish
. Так с помощью отладки удалось найти ошибку — оказывается, был выбран знак <
вместо <=
.
Новички часто расстраиваются из-за ошибок, начинают считать себя невнимательными. На самом деле, в ошибках нет ничего страшного: опытные разработчики допускают их не реже новичков. Сложно научиться писать идеальный код, но можно развивать навыки отладки и насмотренность на ошибки.
Еще новички думают, что опытный разработчик может взглянуть на код и сразу же понять, в чем ошибка. Да, с опытом приходит насмотренность, но все не так просто. По фрагменту кода сложно понять, что пошло не так. Если хотите спросить совет у опытного разработчика, лучше покажите не сам некорректно работающий код, а сообщение об ошибке.