Налагодження (debugging)
Налагодження (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: спостереження за значенням виразу в дебагері.
Пригадаємо попередній урок
range(10) генерує числа від 0 до 9 — верхня межа не входить у діапазон. Це стандартна поведінка, яка спрощує обчислення кількості елементів: range(0, 10) дає 10 чисел.break завершує цикл відразу, а continue пропускає решту тіла й переходить до наступної ітерації.Три типи помилок
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
Читати треба так:
- Останній рядок:
ZeroDivisionError: division by zero— що сталося. - Рядок вище:
return a / b— код, де виникла помилка. - Ще вище:
File "script.py", line 2, in divide— файл, рядок і функція. - Вище за стеком:
result = divide(x, y)— хто викликав цю функцію.
Нижні рядки показують місце помилки, верхні — як туди потрапили. Якщо бачите багато рядків з бібліотек (наприклад, requests або numpy), шукайте перший рядок зі своїм файлом — саме там ваш код передав некоректне значення.
Print-налагодження
Найпростіший спосіб зрозуміти, що відбувається в програмі, — вивести проміжні значення на екран через 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 — рядок, навіть якщо виглядає як число.
Дебагер 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— вивести значення змінноїxn(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 нічого не каже.
Процес:
- Візьміть предмет (іграшка, картинка качки, плюшевий ведмідь) або уявіть людину, яка нічого не знає про ваш код.
- Починайте з першого рядка й говоріть: «Тут я створюю змінну
xзі значенням 5, бо мені потрібно…» - До кожного рядка додавайте «чому»: «Потім я додаю
y, тому що…» - Коли дійдете до рядка, пояснення якого звучить абсурдно («тут я віднімаю 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 у терміналі — корисно для серверних програм. Метод гумової качки допомагає знайти логічні помилки: поясніть код уголос, і баг стане помітним.

Практика
Після лекції переходьте до ноутбука з автоперевіркою. Завдання включають:
- Виправлення програм із синтаксичними помилками за повідомленнями.
- Читання traceback і визначення рядка з помилкою виконання.
- Додавання print-налагодження для пошуку логічної помилки.
- Трасування коду на папері з таблицею змінних.
- Використання дебагера VS Code для крокування по програмі з циклом.
Цикли та ітерація
Цикл while з умовою, цикл for як прохід по ітерованому об'єкту, функція range, інструкції break, continue і else у циклах, вкладені цикли та як зупинити нескінченний цикл.
Рядки і текст
Рядок як незмінна послідовність кодових точок Unicode, індекси й зрізи, функція len, методи split, join, strip, replace, find та інші, оператор in, f-рядки поглиблено, різниця між str і bytes, кодування та декодування, UTF-8.