Ошибки и отладка

Чтение traceback и типичные ошибки

Содержание курса

Воспроизведение и исправление ошибок на примерах

Пройдём полный цикл для каждого из трёх исключений: ошибочный код → traceback → исправление.

NameError: переменная используется до присваивания

print(score)
score = 100

Python выведет:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(score)
NameError: name 'score' is not defined

Читаем снизу: NameError: name 'score' is not defined — имя score Python не знает. Кадр стека: line 1. Смотрим на код: переменная score там есть, она написана правильно — значит, дело не в опечатке. Проблема в порядке: print(score) стоит раньше, чем score = 100. Python выполняет строки сверху вниз и, когда доходит до print(score), присваивание ещё не произошло. Исправление — поменять строки местами:

score = 100
print(score)  # сначала присваивание, потом использование

Программа выводит 100 без ошибок.

Вариация: NameError с той же последней строкой traceback возникает и при опечатке в имени (print(reslt) вместо print(result)). Тогда имя в кавычках сообщения отличается от имени переменной в коде — это сразу подсказывает, что искать опечатку, а не переставлять строки.


TypeError: строка плюс число

age = 25
print('Возраст: ' + age)

Python выведет:

Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print('Возраст: ' + age)
TypeError: can only concatenate str (not "int") to str

Последняя строка сразу говорит: операция + ожидала строку, но получила int. Кадр стека указывает на line 2. Там 'Возраст: ' + age — строку и целое число нельзя складывать напрямую. Два равнозначных способа исправить:

age = 25

# Вариант 1: явное приведение типа
print('Возраст: ' + str(age))

# Вариант 2: f-строка
print(f'Возраст: {age}')

Оба варианта выведут Возраст: 25. F-строка читается чище, особенно когда переменных несколько.


ZeroDivisionError: деление на ноль

x = 10
y = 0
print(x / y)

Python выведет:

Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(x / y)
ZeroDivisionError: division by zero

Последняя строка однозначна. Кадр стека: line 3, выражение x / y. Значение y равно нулю — это и есть проблема. Исправление: проверить делитель перед делением.

x = 10
y = 0

if y != 0:
    print(x / y)
else:
    print('Делить на ноль нельзя')

Теперь программа не падает: она проверяет y заранее и выводит понятное сообщение вместо traceback.


Во всех трёх случаях цикл одинаковый: читаем последнюю строку traceback → находим кадр с номером строки → смотрим на код → исправляем конкретную проблему. Тип исключения каждый раз подсказывал, в какую сторону смотреть: порядок выполнения или опечатка при NameError, конфликт типов при TypeError, нулевой делитель при ZeroDivisionError. В следующем уроке эти же типы исключений можно будет перехватывать блоком try-except — и тогда программа сможет обрабатывать ошибки, не прерывая работу.