$ sudo teach IT
Модуль 2 · Первые шаги · Урок 2.6

Ошибки и как их читать

Ошибка — это не провал, а сообщение от Python о том, что именно пошло не так и где искать причину.

Теория~25 минутНовичокSyntaxErrorIndentationErrorNameErrorTypeErrorValueErrorZeroDivisionErrorTraceback

До сих пор вы уже не раз видели, как программа вдруг останавливается и печатает что-то непонятное вместо результата. Это нормально — такое происходит у каждого, кто пишет код, включая опытных разработчиков. Разница между новичком и профессионалом не в том, что у профессионала нет ошибок, а в том, что он умеет быстро прочитать сообщение об ошибке и понять, что делать дальше. Сегодня вы научитесь тому же.

Traceback — отчёт о падении программы

Когда бытовая техника ломается посреди работы, вы хотите знать не просто "что-то сломалось", а что именно и на каком этапе. Python устроен так же: когда код нельзя выполнить дальше, интерпретатор печатает подробный отчёт о том, в каком файле, на какой строке и по какой причине всё остановилось.

Термин

Traceback (дословно "обратный путь") — текст, который Python печатает при аварийном завершении программы. Он показывает цепочку мест в коде, которая привела к ошибке, и заканчивается типом ошибки и её описанием. Слово "исключение" (exception) — ещё одно название для такой ошибки во время выполнения программы, вы будете часто встречать его в документации.

Python · Программа с ошибкой
a = 100
b = 0
result = a / b
print(result)
Что напечатает Python
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    result = a / b
             ~~^~~
ZeroDivisionError: division by zero

Разбор по строкам:

  • Traceback (most recent call last): — заголовок, он всегда одинаковый и просто сообщает, что дальше пойдёт разбор произошедшего.
  • File "main.py", line 3, in <module> — в каком файле и на какой строке остановился код.
  • result = a / b — сама строка кода, где случилась проблема, а стрелки ~~^~~ под ней указывают на конкретное место.
  • ZeroDivisionError: division by zero — самая важная строка. Слева тип ошибки, справа после двоеточия — человеческое объяснение.
Главное правило чтения Traceback: начинайте с последней строки. В ней тип ошибки и её описание — в девяти случаях из десяти этого достаточно, чтобы понять, что делать. Остальные строки нужны, только если непонятно, где именно в коде искать проблему.

SyntaxError — нарушены правила языка

Представьте фразу без глагола или скобку, которую открыли, но забыли закрыть. Python работает так же: если код записан с нарушением грамматики языка, интерпретатор не может его даже начать выполнять.

Термин

SyntaxError (буквально "ошибка синтаксиса") — сигнал о том, что текст программы не соответствует грамматике Python: например, не закрыта скобка или не закрыта кавычка. Такая ошибка обнаруживается ещё до запуска, потому что интерпретатор сначала читает весь код, а только потом выполняет его.

Python · Незакрытая скобка
print("Привет, мир!"
Что напечатает Python
  File "main.py", line 1
    print("Привет, мир!"
                        ^
SyntaxError: '(' was never closed
Последняя строка говорит прямым текстом: скобка ( "никогда не была закрыта". Решение — дописать ) в конце строки: print("Привет, мир!"). Та же логика работает и с кавычками: сколько открыли — столько же и закрываем.

IndentationError — ошибка отступов

В обычном тексте лишний пробел в начале строки никто не заметит. В Python отступы — часть самого языка: по ним интерпретатор понимает, к какому блоку кода относится строка. Если отступ стоит там, где Python его не ожидает, код не запустится.

Термин

IndentationError — ошибка отступов: где-то в файле отступ (обычно это пробелы в начале строки) стоит не там, где его ждёт Python. Стандарт языка — отступ в 4 пробела для каждого уровня вложенности; смешивать пробелы и символ табуляции в одном файле нельзя.

Python · Случайный отступ
name = "Анна"
    age = 25
print(name, age)
Что напечатает Python
  File "main.py", line 2
    age = 25
IndentationError: unexpected indent
Строка age = 25 начинается с четырёх лишних пробелов, хотя ничего перед ней не просило начать блок с отступом — отсюда слово unexpected ("неожиданный") в тексте ошибки. Уберите лишние пробелы в начале строки — и код снова заработает.

NameError — такого имени ещё нет

Если попросить официанта принести блюдо, которого нет в меню, он честно скажет: "у нас такого нет". Python реагирует так же, когда вы обращаетесь к переменной, которую ещё не создали — или создали, но под другим именем.

Термин

NameError — ошибка "неизвестное имя": в коде используется имя переменной, которого Python не знает. Так бывает, если переменную забыли создать строкой имя = значение раньше по коду, либо если в имени допущена опечатка — Python различает регистр букв, поэтому name и Name для него разные слова.

Python · Опечатка в имени
username = "Мария"
print(usernme)
Что напечатает Python
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(usernme)
          ^^^^^^^
NameError: name 'usernme' is not defined
Переменная называется username, а напечатана usernme — пропущена буква. Для Python это два разных имени, второго из которых не существует, о чём и сообщает последняя строка.

TypeError — несовместимые типы

Линейкой нельзя разделить пирог — инструмент не подходит для такой операции. В программировании то же самое: у каждого типа данных свой набор допустимых действий, и Python не станет угадывать, что вы имели в виду, если вы просите его сделать что-то несовместимое.

Термин

TypeError — ошибка типа: вы попросили выполнить операцию над значениями, которые для неё не подходят. Самый частый случай у новичков — сложение строки (str) и числа (int) знаком +: для чисел + означает сложение, а для строк — склеивание, и Python не смешивает эти два поведения автоматически.

Python · Строка плюс число
age = "20"
result = age + 5
print(result)
Что напечатает Python
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    result = age + 5
             ~~~~^~~
TypeError: can only concatenate str (not "int") to str
Переменная age хранит строку "20", а 5 — число. Текст ошибки объясняет правило: к строке можно "приклеить" (concatenate) только другую строку. Чтобы сложить их как числа, сначала превратите строку в число: result = int(age) + 5.

ValueError — тип верный, а значение — нет

Бланк просит вписать число, а вы пишете в поле текст — формат поля правильный (строка), но содержимое не годится. У Python есть отдельная ошибка именно для такого случая: тип данных подходящий, но конкретное значение использовать нельзя.

Термин

ValueError — ошибка значения: сама операция применена к значению правильного типа, но с содержимым, которое для неё не подходит. Чаще всего новички видят её при попытке превратить нечисловую строку в число функцией int() или float().

Python · Нечисловая строка
number = int("двадцать")
print(number)
Что напечатает Python
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    number = int("двадцать")
             ^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'двадцать'
int() принимает строку, только если внутри неё записаны цифры — например "20". Слово "двадцать" буквами число не является, поэтому int() честно отказывается его превращать и объясняет почему.
Реальный сценарий: если программа спрашивает у пользователя число через input(), а тот случайно ошибается с клавишами, результат int() от такого ответа — ровно эта ошибка.

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

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

Термин

ZeroDivisionError — ошибка деления на ноль: возникает при делении (/ или //) или взятии остатка (%) на переменную или число, равные нулю.

Python · Делитель равен нулю
price = 500
people = 0
share = price / people
Что напечатает Python
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    share = price / people
            ~~~~~~^~~~~~~~
ZeroDivisionError: division by zero
Переменная people равна нулю, а поделить стоимость на ноль человек нельзя — Python явно называет проблему вместо тихого сбоя.

Ответ проверки на платформе — не то же самое, что ошибка Python

Бывает так: код отработал без единого Traceback, а кнопка "Проверить" всё равно говорит, что задача не решена. Это не поломка платформы — программа выполнилась, но результат получился не тот, что нужен.

Термин

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

Если проверка не прошла, платформа честно показывает:

  • Название проверки — что именно сравнивалось, например "сумма чисел от 1 до 5".
  • Ожидалось — какое значение должно было получиться.
  • Получено — какое значение реально оказалось у вас.
Сравните "ожидалось" и "получено" — и почти всегда сразу станет видно, в какую сторону ошиблась логика: не тот знак операции, забытая переменная, число на единицу больше или меньше нужного.

Как правильно гуглить ошибки

Опытные разработчики каждый день ищут решения своих ошибок в интернете — это обычная часть работы. Разница только в том, что они умеют быстро находить нужный ответ, потому что правильно формулируют запрос.

1. Копируйте последнюю строку Traceback

В ней тип ошибки и описание — например TypeError: can only concatenate str (not "int") to str. Это и есть самый точный поисковый запрос.

2. Добавьте слово "python" и прикладывайте свой код при просьбе о помощи

Слово "python" отсекает ответы для других языков. А ментору, в чате или ИИ-помощнику стоит показывать не только текст ошибки, но и сам код — фраза "не работает" без этого ничего не объясняет.

Частые ошибки

Читать только первую строку Traceback

Новички часто пугаются длинного текста и смотрят только на самый верх, где написано "Traceback (most recent call last)". Но там нет ответа — тип и суть ошибки всегда в самом низу.

Переписывать код заново вместо того, чтобы прочитать ошибку

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

Что важно запомнить

1.
Traceback читайте снизу вверх: последняя строка — тип ошибки и её описание, этого почти всегда достаточно.
2.
SyntaxError и IndentationError — код записан или расставлен неправильно, программа даже не запускается.
3.
NameError — переменной с таким именем не существует; TypeError — действие не подходит для этих типов данных; ValueError — тип верный, а содержимое нет; ZeroDivisionError — попытка поделить на ноль.
4.
Проверка на платформе показывает "ожидалось" и "получено" отдельно от Python — это подсказка про логику, а не про синтаксис.
5.
Гуглить текст ошибки — нормальная привычка любого разработчика, а не признак слабых знаний.

Проверьте себя

3 вопроса

Исправление ошибок в коде

Дан код с двумя ошибками: опечатка в имени переменной внутри вывода и попытка сложить строку с числом. Найдите и исправьте обе ошибки, чтобы программа работала без падений: имя остаётся в name, возраст — в age.