Как отладить код: советы для начинающих

Покажем, как отладить сложный код просто и без паники. Поговорим о ключевых инструментах и дадим советы, которые помогут даже начинающим разработчикам быстро найти проблему.

494 открытий3К показов
Как отладить код: советы для начинающих

В 2017 году Amazon потерял сотни миллионов долларов из-за одной опечатки.

Сбой длился 4 часа и привёл к сбою в работе Netflix, Airbnb и даже Комиссии по ценным бумагам и биржам США. А виной всему человеческий фактор: сотрудник занимался рутинной отладкой системы, ошибся в команде и отключил сервера, которые отключать было нельзя.

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

Так отлаживать или дебажить?

Дебажить –– англицизм, который значит то же самое. Используйте тот термин, который вам нравится. А мы будем их чередовать.

Итак, отладка — процесс выявления и исправления ошибок в программном коде.

Ошибки бывают разные:

Синтаксические

Синтаксическая ошибка –– это, например, забытая закрывающаяся скобка или пропущенный отступ.

Здесь синтаксическая ошибка в том, что мы забыли двоеточие в первой строке:

			def add(a, b) #ошибка тут, мы забыли двоеточие
    return a + b
		

В Python обязательно нужно ставить двоеточие после объявления функции. Без этого язык не поймет, что за двоеточием следует тело функции. Поэтому программа выполнена не будет.

Как правильно:

			def add(a, b):
    return a + b
		

Логические

Логические ошибки –– неправильная логика программы. Код может выполняться без проблем в синтаксисе и не выбрасывать исключения, но при этом не давать ожидаемого результата. Такие ошибки трудно отследить, потому что Python не сообщает о них явно.

Допустим, мы пишем программу для проверки чётности:

			def is_even(number):
    return number % 2 == 1  # Здесь логическая ошибка

print(is_even(4))  # Ожидаем True, но получаем False
		

Вместо проверки number % 2 == 0 проверяется number % 2 == 1. Это логическая ошибка.

Исключения

Исключения — ошибки, которые возникают во время выполнения программы. Например, деление на ноль или попытка получить элемент списка по индексу, которого нет.

Разберём деление на ноль. Это действие вызовет исключение ZeroDivisionError:

			def divide(a, b):
    return a / b

print(divide(10, 0))
		
			ZeroDivisionError: division by zero
		

Такие исключения можно обрабатывать, чтобы программа не упала. Используем try-except:

			def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return "no division by zero in this house!"

print(divide(10, 0))
		

Итак, каждая ошибка требует своего подхода. Но если знать, как правильно дебажить, вы сможете значительно ускорить процесс и сделать свой код качественным, понятным и надёжным.

Перейдём к инструкции по отладке.

Шаг 1: Анализируем ошибки и логи

Перед тем, как отлаживать код, важно понять: что именно пошло не так? Поэтому первый шаг –– анализ.

Типы ошибок мы уже разобрали, поэтому будет полегче. Иногда их не получается увидеть сразу в коде –– если бы всё было так просто! Тогда на помощь приходят логи, которые предоставляет программа или ваша IDE.

Что с ними делать:

  1. Изучите сообщение об ошибке. Важно понять, где и почему произошёл сбой. Обычно сообщение указывает тип ошибки и место, где она возникла. Мы уже видели такое поведение в предыдущем разделе, когда забыли поставить двоеточие;
  2. Проверьте логи. В логах будут важные данные об ошибке. Обратите внимание на ключевые слова: Error или Exception;
  3. Воспроизведите ошибку. Попробуйте выполнить код несколько раз. Возможно, это был случайный баг, который больше не повторится.
Как отладить код: советы для начинающих 1

Шаг 2: Разделяем задачу на более мелкие части

Сломанный код лучше разбить на более мелкие и понятные части. Это поможет вам найти ошибку быстрее, так как вы точно определите, где её точно нет.

Как это работает:

Если ошибка возникает в сложном фрагменте, то лучше разделить его на более мелкие шаги.

Пример: Если программа загружает файл, обрабатывает данные и записывает результат, проверьте отдельно каждую функцию:

  • Загружается ли файл?
  • Обработались ли данные?
  • Успешно ли записывается результат?

Также можно сузить область поиска ошибки. Если задача большая, начните с проверки небольших фрагментов кода, чтобы изолировать проблемный участок. Загоните ошибку в угол.

Это лучше, чем хаотично бросаться то в одну, то в другую часть кода и искать иголку в стоге сена.

Шаг 3: Воссоздаём проблему

Репродукция ошибки — самая важная задача. Чтобы понять, как исправить ошибку, вам нужно её увидеть и поймать. Иногда она проявляется только при определенных условиях, а при каких –– неясно.

Тут стоит схитрить:

  • Попробуйте воспроизвести ошибку при разных входных данных. Может быть, строка не ломает программу, а число –– да;
  • Пользуйтесь инструментами отладки и отслеживайте каждый шаг программы.

И тут мы подобрались к самому интересному. Пока что мы говорили о том, как решать проблему. Но не упомянули, с помощью чего. Исправляемся.

Отладчики и логирование

Отладчики встроены в большинство IDE. Например, в PyCharm или Visual Studio есть встроенные отладчики, с помощью которых можно поставить точки останова.

Точка останова (breakpoint) — инструмент, с помощью которого вы можете остановить программу на определенном этапе и изучить её состояние. Например, проверить, какие значения принимают переменные или что именно происходит перед вызовом ошибки.

Как это работает:

  1. Установите точку останова в нужной строке;
  2. Запустите программу в режиме отладки;
  3. Выполнение остановится на этой строке: изучите текущие данные.

Разберём на примере Visual Studio:

Напишем небольшую функцию, в которой рассчитывается площадь прямоугольника:

			def main():
   width = 5
   height = 10
   result = width * height
   print(f"Площадь: {result}")

main()
		

Поставим точки останова на переменных width, height и result:

Как отладить код: советы для начинающих 2

Перейдём вот в эту панельку:

Как отладить код: советы для начинающих 3

И запустим дебаггинг:

Как отладить код: советы для начинающих 4

После запуска в редакторе появится новая панелька –– для управления отладкой:

Как отладить код: советы для начинающих 5

С помощью неё можно остановить или перезапустить отладку, перейти к следующей точке останова и так далее.

В панели слева появятся значения, за которыми мы следим:

Как отладить код: советы для начинающих 6

Здесь вы можете увидеть, чему равна каждая переменная.

Напишем функцию с ошибкой, которую уже разбирали:

			def main():
   colors = ['violet','beige', 'teal']
   print(colors[4])

main()
		

Мы пытаемся получить элемент, индекс которого не существует. Красная плашка предупреждает, что возникло исключение:

Как отладить код: советы для начинающих 7

List index out of range –– такого индекса в списке нет. Вроде всё понятно, но можно разобраться.

Сбоку мы видим список colors, его элементы и длину len(). В Python, как и во многих других языках, отсчёт начинается с 0. Если в списке 3 элемента, то индекс последнего –– 2. Поэтому мы и получаем ошибку.

Помимо точек останова можно следить за стеком вызовов.

Стек вызовов — цепочка вызванных функций. Она показывает, что происходит на каждом шаге программы.

Это особенно важно при сложных ошибках, скрытых глубоко в коде. Перепишем немного и сделаем несколько программ:

			colors = ['violet', 'beige', 'teal']

def get_favorite_color(index):
   return colors[index]


def display_favorite_color(index):
   color = get_favorite_color(index)
   print(f"Ваш любимый цвет: {color}")


def main():
   display_favorite_color(4)


main()
		

Ошибка всё ещё на месте, но теперь её появление происходит не сразу в функции main, а глубже.

И стек вызовов нам показывает, что сначала выполняется main, затем display_favorite_color и уже потом get_favorite_color, где и живёт ошибка:

Как отладить код: советы для начинающих 8

Эту проблему можно решить с помощью try-except. Советуем попробовать самостоятельно🙂.

И последний способ отладки, который разберём –– логирование. Можно использовать print() или модуль, который уже заботливо написали за нас. Результат одинаковый — вывод нужных данных в определённое время. Так мы поймём, что лежит в переменной и почему программа ломается.

Примеры с print мы уже разбирали в предыдущих шагах. Метод простой и лёгкий –– то, что нужно для новичков.

Разберём вариант посложнее с модулем logging. Его нужно импортировать и настроить:

			import logging #импорт

logging.basicConfig(level=logging.DEBUG, #строка 3
format='%(asctime)s - %(levelname)s - %(message)s',
) #настройка

def get_favorite_color(index):
   logging.info("Получение цвета")
   return colors[index]

def display_favorite_color(index):
   color = get_favorite_color(index)
   logging.debug(f"Ваш любимый цвет: {color}")
def main():
   display_favorite_color(2)

main()
		

Теперь подробнее про конфигурацию. В logging есть несколько типов сообщений:

  • Отладочные –– DEBUG. Они показывают подробности о значениях переменных или работе отдельных функций;
  • Информационные –– INFO. В них можно прописывать статусы выполнения программы;
  • Предупреждения –– WARNING. Сообщения с потенциальными проблемами;
  • Ошибки –– ERROR и CRITICAL. 

Мы указали, что хотим видеть все сообщения с помощью строки 3. Теперь в консоли будет отображаться все, что нужно: предупреждения, ошибки и обычные сообщения отладки.

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

Как отладить код: советы для начинающих 9

Это намного удобнее, чем прописывать все данные в print вручную.

Если нам нужны только ворнинги, то меняем конфигурацию:

			logging.basicConfig(level=logging.WARNING)
		

Шаг 4: Тестируем — юнит-тесты и их роль

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

Юнит-тесты — отличный способ проверять, что каждый блок вашего кода работает как положено.

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

Для этого можно использовать pytest или unittest.

Давайте поработаем с pytest. Напишем в файле main.py очень простую функцию:

			def main(num):
   return num ** 2
		

Функция принимает число и возвращает квадрат числа.

Напишем тест. Для этого нужно установить pytest в свою IDE и создать файлик. Например, test.py:

			from main import main

def test_main():
   assert main(2) == 4
		

Наша гипотеза: 2 в квадрате равно 4. Для того, чтобы её проверить, используем assert.

Если в терминале запустить команду pytest test.py, то увидим, что всё прошло успешно:

Как отладить код: советы для начинающих 10

Если же заменить 4 на 5, то тест упадёт. Так как 2 в квадрате –– не 5:

Как отладить код: советы для начинающих 11

Советы по улучшению процесса отладки

Мы разобрались, как дебажить и тестировать код. Напоследок дадим три базовых совета, которые актуальны не только для Python, но и для любого языка программирования.

Делите код на небольшие модули

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

Пишите автоматические тесты

Автоматическое тестирование позволяет ловить ошибки на ранних этапах. Вы можете и не увидеть их сразу. Зато они вас видят.

Поэтому после написания каждой новой функции добавляйте тесты. Это избавит от сюрпризов в будущем, когда изменение одной программы неожиданно ломает другую.

Комментируйте код

Не забывайте комментировать код. Объяснять, зачем и как работает каждая функция. Комментарии помогут и вам, и вашей команде быстрее разобраться в коде, особенно спустя несколько месяцев.

Ну и конечно, называйте функции и переменные понятно. Не усложняйте жизнь себе и коллегам. То, что изначально сделано качественно и с умом, с меньшей вероятностью придётся дебажить.

Но если всё-таки пришлось, следуйте нашей инструкции, и всё обязательно получится.

Следите за новыми постами
Следите за новыми постами по любимым темам
494 открытий3К показов