Python Core

Налагодження (debugging)

Типи помилок — синтаксичні, виконання та логічні; як читати traceback знизу вгору; print-налагодження; дебагер VS Code з breakpoint, step over і step into; вбудована функція breakpoint(); метод гумової качки.

Налагодження (debugging)

Баги неминучі — і це нормально

Ніхто не пише ідеальний код з першого разу. Баг (bug) — це відхилення поведінки програми від очікуваної, а налагодження (debugging) — процес пошуку та виправлення цих помилок. Назва походить від реального випадку 1947 року, коли метелик (bug) застряг у комп'ютері Mark II і спричинив несправність. Вміння знаходити помилки так само важливе, як і писати код.

🎯 Мета лекції

  • Розрізняти синтаксичні помилки, помилки виконання й логічні помилки.
  • Читати traceback знизу вгору і знаходити місце помилки.
  • Налагоджувати код через print, простежуючи стан змінних.
  • Використовувати дебагер VS Code: breakpoint, step over, step into, watch.
  • Пояснювати, навіщо потрібна функція breakpoint().
  • Застосовувати метод гумової качки для пошуку логічних помилок.

🔑 Ключові терміни

  • Баг (bug): помилка в програмі.
  • Налагодження (debugging): процес пошуку та виправлення помилок.
  • Traceback: звіт Python про помилку зі стеком викликів.
  • Breakpoint: точка зупинки виконання програми в дебагері.
  • Step over / step into: покрокове виконання коду.
  • Watch: спостереження за значенням виразу в дебагері.

Пригадаємо попередній урок

Три типи помилок

Python розрізняє помилки за моментом виявлення та наслідками. Синтаксичні виявляються до запуску, помилки виконання зупиняють програму, а логічні дають неправильний результат, але не падають.

Синтаксичні помилки

Синтаксична помилка (syntax error) — це порушення правил мови. Python не може прочитати код і відмовляється його виконувати. Найчастіше це забуті двокрапки, незакриті дужки або неправильні відступи:

if x > 5
    print("більше")
  File "script.py", line 1
    if x > 5
            ^
SyntaxError: expected ':'

Python вказує на місце, де очікував знак :. Синтаксичні помилки найлегші для виправлення: достатньо прочитати повідомлення й додати те, що пропущено. У VS Code редактор підсвічує такі помилки червоним підкресленням.

Помилки виконання

Помилка виконання (runtime error, exception) виникає під час роботи програми. Синтаксис правильний, код запустився, але в певний момент щось пішло не так — наприклад, програма спробувала поділити на нуль або перетворити рядок "abc" у число:

x = 10
y = 0
result = x / y
Traceback (most recent call last):
  File "script.py", line 3, in <module>
    result = x / y
ZeroDivisionError: division by zero

Python зупиняється і друкує traceback — звіт із типом помилки (ZeroDivisionError), файлом, рядком і самим кодом. Такі помилки вимагають перевірки значень перед операцією: if y != 0: перед діленням.

Логічні помилки

Логічна помилка (logic error) — найпідступніша. Програма працює без збоїв, але результат неправильний. Python не помічає проблеми, бо порушення логіки — це ваша думка, а не правило мови:

# Хочемо суму від 1 до 10
total = 0
for i in range(10):
    total += i
print(total)
45

Очікували 55, отримали 45. Причина: range(10) дає 0..9, а не 1..10. Python виконав те, що ви написали, а не те, що мали на увазі. Логічні помилки знаходять через трасування коду, print-налагодження або дебагер.

Хибне уявлення: «Якщо програма не падає, вона правильна». Логічна помилка не викликає виняток, але може спричинити фінансові втрати (помилковий розрахунок) або неправильну відповідь користувачу.

Читання traceback знизу вгору

Коли Python зустрічає помилку виконання, він друкує traceback — стек кадрів з моменту виклику до рядка, де сталася проблема. Типова помилка: студент починає читати зверху, де написано Traceback (most recent call last):, і не розуміє, що саме не так. Найважливіша інформація — внизу.

Структура traceback:

Traceback (most recent call last):
  File "script.py", line 6, in <module>
    result = divide(x, y)
  File "script.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero

Читати треба так:

  1. Останній рядок: ZeroDivisionError: division by zero — що сталося.
  2. Рядок вище: return a / b — код, де виникла помилка.
  3. Ще вище: File "script.py", line 2, in divide — файл, рядок і функція.
  4. Вище за стеком: result = divide(x, y) — хто викликав цю функцію.

Нижні рядки показують місце помилки, верхні — як туди потрапили. Якщо бачите багато рядків з бібліотек (наприклад, requests або numpy), шукайте перший рядок зі своїм файлом — саме там ваш код передав некоректне значення.

У Python 3.15 traceback підсвічений кольором: тип помилки червоний, файли зелені, рядки сині. Це полегшує читання в терміналі.

Найпростіший спосіб зрозуміти, що відбувається в програмі, — вивести проміжні значення на екран через print. Print-налагодження ефективне для коротких програм і лінійної логіки, де достатньо побачити послідовність змін.

Виведення значень змінних

Додайте print після кожної операції, яка змінює стан:

x = 5
y = 10
print("DEBUG: x =", x, ", y =", y)

result = x + y * 2
print("DEBUG: result =", result)
DEBUG: x = 5 , y = 10
DEBUG: result = 25

Префікс DEBUG: допомагає відрізнити налагоджувальний вивід від результатів програми. Після виправлення помилки такі рядки легко знайти й видалити.

Маркери виконання

У розгалуженнях корисно бачити, яка гілка спрацювала:

x = int(input("Введіть число: "))

if x > 0:
    print("DEBUG: x додатне")
    result = x * 2
else:
    print("DEBUG: x від'ємне або нуль")
    result = 0

print("DEBUG: result =", result)

Вхід 5:

DEBUG: x додатне
DEBUG: result = 10

Вхід -3:

DEBUG: x від'ємне або нуль
DEBUG: result = 0

Тепер відразу видно, чому результат такий, без ментального виконання всіх умов.

Виведення в циклах

У циклі корисно бачити значення лічильника та змінної, що накопичує результат:

total = 0
for i in range(1, 6):
    print(f"DEBUG: i = {i}, total до додавання = {total}")
    total += i
    print(f"DEBUG: total після додавання = {total}")

print("Фінальний результат:", total)
DEBUG: i = 1, total до додавання = 0
DEBUG: total після додавання = 1
DEBUG: i = 2, total до додавання = 1
DEBUG: total після додавання = 3
DEBUG: i = 3, total до додавання = 3
DEBUG: total після додавання = 6
DEBUG: i = 4, total до додавання = 6
DEBUG: total після додавання = 10
DEBUG: i = 5, total до додавання = 10
DEBUG: total після додавання = 15
Фінальний результат: 15

Кожен крок розкладений: видно, як змінюється total, і легко помітити, якщо значення стрибає неправильно.

Виведення типів

Частіша помилка новачка: очікували число, отримали рядок, бо забули int(). Виведення типу дає підказку:

x = input("Введіть число: ")
print("DEBUG: x =", x, ", type =", type(x))

y = int(x)
print("DEBUG: y =", y, ", type =", type(y))

Вхід 42:

DEBUG: x = 42 , type = <class 'str'>
DEBUG: y = 42 , type = <class 'int'>

Тепер зрозуміло, що x — рядок, навіть якщо виглядає як число.

Print-налагодження неефективне для великих програм або циклів із тисячами ітерацій. У таких випадках краще використовувати дебагер, який дозволяє зупинитися в потрібному місці та оглянути стан без зміни коду.

Дебагер VS Code

Дебагер (debugger) — інструмент, який дозволяє зупинити виконання програми в обраній точці та крокувати по рядках, дивлячись на значення змінних у реальному часі. У VS Code дебагер вбудований і працює без додаткового налаштування для Python.

Breakpoint — точка зупинки

Breakpoint (точка зупинки) — позначка на рядку, де дебагер має зупинитися. Щоб поставити breakpoint у VS Code, клацніть ліворуч від номера рядка (з'явиться червона крапка) або натисніть F9, коли курсор на потрібному рядку.

x = 5
y = 10            # ← breakpoint тут
result = x + y
print(result)

Запустіть програму через F5 (або меню Run → Start Debugging). Виконання зупиниться на рядку y = 10, жовта стрілка покаже поточний рядок. У лівій панелі «Variables» відобразяться всі змінні поточного кадру: x = 5, y ще не існує. Натисніть F10 (Step Over), щоб виконати цей рядок — тепер y = 10 з'явиться в списку.

Step Over і Step Into

Step Over (F10) виконує поточний рядок і переходить до наступного в тому самому кадрі. Якщо рядок містить виклик функції, дебагер виконає її повністю й не заходить усередину.

Step Into (F11) заходить усередину функції, щоб крокувати по її тілу:

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

x = 5
y = 10
result = add(x, y)  # breakpoint тут
print(result)

Якщо на рядку result = add(x, y) натиснути F10, дебагер виконає add і зупиниться на print. Якщо натиснути F11, дебагер перейде до рядка return a + b усередині add і покаже локальні змінні a = 5, b = 10.

Step Out (Shift+F11) завершує виконання поточної функції й повертається в рядок виклику.

Watch — спостереження за виразами

Панель Watch дозволяє додати вираз і бачити його значення на кожному кроці. Наприклад, додайте x + y — дебагер покаже результат, навіть якщо цього виразу немає в коді. Це корисно для перевірки проміжних обчислень без зміни програми.

Якщо програма запитує ввід через input(), дебагер VS Code відкриває термінал усередині редактора — туди треба ввести дані та натиснути Enter.

Функція breakpoint()

Python 3.7 додав вбудовану функцію breakpoint(), яка зупиняє програму в цьому місці й запускає pdb (Python Debugger) — інтерактивний дебагер у терміналі. Це зручно, коли немає доступу до VS Code або потрібно налагодити програму, що запущена через термінал:

x = 5
y = 10
breakpoint()      # зупинка тут
result = x + y
print(result)

Запуск:

python script.py

Вивід:

> /path/to/script.py(4)<module>()
-> result = x + y
(Pdb) 

У режимі (Pdb) можна ввести:

  • p x — вивести значення змінної x
  • n (next) — наступний рядок (як Step Over)
  • s (step) — увійти в функцію (як Step Into)
  • c (continue) — продовжити до наступного breakpoint або кінця
  • q (quit) — вийти з дебагера
  • h (help) — список команд

Приклад сесії:

(Pdb) p x
5
(Pdb) p y
10
(Pdb) n
> /path/to/script.py(5)<module>()
-> print(result)
(Pdb) p result
15
(Pdb) c
15

breakpoint() корисна для серверних програм або скриптів, що працюють без графічного інтерфейсу. У VS Code вона теж працює, але ручні breakpoints зручніші.

breakpoint() викликає функцію sys.breakpointhook(), яка за замовчуванням запускає pdb.set_trace(). Це можна перевизначити через змінну оточення PYTHONBREAKPOINT=0, щоб вимкнути всі breakpoints одразу.

Метод гумової качки

Метод гумової качки (rubber duck debugging) — це техніка, коли ви пояснюєте код уголос уявній качці (або колезі, котові, іграшці). Поки пояснюєте, що робить кожен рядок і чому, мозок включає іншу частину мислення, і помилка стає помітною. Це особливо ефективно для логічних помилок, де traceback нічого не каже.

Процес:

  1. Візьміть предмет (іграшка, картинка качки, плюшевий ведмідь) або уявіть людину, яка нічого не знає про ваш код.
  2. Починайте з першого рядка й говоріть: «Тут я створюю змінну x зі значенням 5, бо мені потрібно…»
  3. До кожного рядка додавайте «чому»: «Потім я додаю y, тому що…»
  4. Коли дійдете до рядка, пояснення якого звучить абсурдно («тут я віднімаю 1, бо… хм, чому я це роблю?») — знайшли проблему.

Приклад. Код рахує факторіал, але дає 0:

n = 5
factorial = 1

for i in range(n):
    factorial *= i

print(factorial)

Пояснення качці:

«Я створюю n = 5, бо хочу факторіал 5. Потім factorial = 1, бо це нейтральний елемент для множення. Тепер цикл від 0 до 4… хм, стоп. Нуль? i буде 0 на першому колі, і factorial множиться на 0. От і проблема!»

Виправлення: for i in range(1, n + 1).

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

Якщо пояснюєте живій людині, не треба, щоб вона була програмістом. Навпаки, пояснення новачку змушує спрощувати й розкладати логіку на кроки, що часто й виявляє баг.

Підсумок

Налагодження — це не біда, а нормальна частина розробки. Знайте три типи помилок: синтаксичні (до запуску), виконання (під час роботи) і логічні (неправильний результат). Читайте traceback знизу вгору — найважливіша інформація в останньому рядку. Використовуйте print-налагодження для простих випадків і дебагер VS Code для складних: ставте breakpoint, крокуйте через F10 і F11, дивіться змінні. Функція breakpoint() запускає pdb у терміналі — корисно для серверних програм. Метод гумової качки допомагає знайти логічні помилки: поясніть код уголос, і баг стане помітним.

Практика

Після лекції переходьте до ноутбука з автоперевіркою. Завдання включають:

  1. Виправлення програм із синтаксичними помилками за повідомленнями.
  2. Читання traceback і визначення рядка з помилкою виконання.
  3. Додавання print-налагодження для пошуку логічної помилки.
  4. Трасування коду на папері з таблицею змінних.
  5. Використання дебагера VS Code для крокування по програмі з циклом.
Кожна виправлена помилка — крок до кращого розуміння Python. Не засмучуйтесь, коли щось не працює: баги — це нормально, а вміння їх знаходити відрізняє новачка від досвідченого розробника.
Copyright © 2026