Перейти к содержимому
Теория · Первая программа · урок 3 из 7

Отступы и ошибки

Вернёмся к машине python на столе. Прежде чем печатать, она просматривает весь лист: правильно ли записаны строки. Если на листе есть строка, которую по правилам нельзя прочитать, машина возвращает лист и не печатает ничего. Даже верные строки над ошибкой остаются ненапечатанными.

Посмотрим на такой лист. Во второй строке не закрыта скобка, а первая написана верно — но и она ничего не напечатает:

Python
print("one")
print("two"  # ✗
TEXT
SyntaxError: '(' was never closed

Интерпретатор сначала проверяет весь файл по правилам записи и только потом выполняет его. Ошибку SyntaxError, найденную при проверке, он сообщает до выполнения первой строки, поэтому one не появляется.

Этот вопрос часто задают на собеседовании: почему ошибка в последней строке не дала выполниться первой? Ответ: перед запуском интерпретатор разбирает весь файл целиком. Нарушенное правило записи он находит раньше, чем выполняет хоть одну строку.

Отступ и блок

Отступ — пробелы в начале строки, и в Python они входят в правила записи. Отступ показывает, какие строки составляют блок — группу строк, подчинённых одной строке над ними.

У блока два правила:

  • он может начаться только после строки, которая кончается двоеточием;
  • его строки сдвинуты вправо, принято на 4 пробела.

В программах из одних вызовов print строк с двоеточием нет, поэтому каждая строка начинается с первого символа. Лишний отступ интерпретатор находит при той же проверке файла и сообщает ошибку IndentationError.

Ошибка во время работы

Опечатку в имени функции проверка файла не замечает: правила записи не нарушены. Машина принимает лист и начинает печатать.

Python
print("one")  # one
print("two")  # two
pritn("three")  # ✗
print("four")
TEXT
NameError: name 'pritn' is not defined. Did you mean: 'print'?

Давайте разберём, что происходит при запуске:

  1. Первая строка печатает one.
  2. Вторая строка печатает two.
  3. На третьей интерпретатор ищет функцию pritn, не находит её и останавливает программу с ошибкой NameError.
  4. Четвёртая строка уже не выполняется, и four не появляется.

Так ведёт себя любая ошибка, которую находит только выполнение. Строки выше неё уже отработали, и их вывод остаётся на ленте.

Как читать трассировку

Сообщение об ошибке занимает несколько строк и называется трассировкой. У ошибки из примера выше она устроена так:

  1. Traceback (most recent call last): — заголовок: ошибка случилась во время работы.
  2. File "…/hello.py", line 3, in <module> — путь к файлу и номер строки с ошибкой.
  3. Сама строка pritn("three"), а под ней значки ^, которые отмечают место ошибки.
  4. NameError: name 'pritn' is not defined. Did you mean: 'print'? — вид ошибки и причина.

Читайте трассировку с последней строки: она сразу говорит, что случилось. Номер строки из второй строки трассировки подскажет, где искать.

У ошибок, найденных при проверке файла, строки Traceback нет. Но последняя строка устроена так же: вид ошибки, двоеточие и причина.

Частая ошибка

Перед вызовом случайно оказался пробел:

Python
print("one")
 print("two")  # ✗
TEXT
IndentationError: unexpected indent

Одного пробела хватает: строка выше не кончается двоеточием и не открывает блок. Поэтому отступ во второй строке лишний. Ошибку находит проверка файла, поэтому не печатается даже one. Исправление — удалить пробелы в начале строки.

Главное

  • Перед запуском интерпретатор проверяет весь файл, и ошибка записи — SyntaxError или IndentationError — не даёт выполниться ни одной строке.
  • Отступ открывает блок, а блок может начаться только после строки с двоеточием.
  • Ошибка во время работы, например NameError, останавливает программу на своей строке, и вывод строк выше уже напечатан.
  • Трассировку читают с последней строки: там вид ошибки и причина.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом