Отступы и ошибки
Вернёмся к машине python на столе. Прежде чем печатать, она просматривает весь лист: правильно ли записаны строки. Если на листе есть строка, которую по правилам нельзя прочитать, машина возвращает лист и не печатает ничего. Даже верные строки над ошибкой остаются ненапечатанными.
Посмотрим на такой лист. Во второй строке не закрыта скобка, а первая написана верно — но и она ничего не напечатает:
print("one")
print("two" # ✗SyntaxError: '(' was never closedИнтерпретатор сначала проверяет весь файл по правилам записи и только потом выполняет его. Ошибку SyntaxError, найденную при проверке, он сообщает до выполнения первой строки, поэтому one не появляется.
Этот вопрос часто задают на собеседовании: почему ошибка в последней строке не дала выполниться первой? Ответ: перед запуском интерпретатор разбирает весь файл целиком. Нарушенное правило записи он находит раньше, чем выполняет хоть одну строку.
Отступ и блок
Отступ — пробелы в начале строки, и в Python они входят в правила записи. Отступ показывает, какие строки составляют блок — группу строк, подчинённых одной строке над ними.
У блока два правила:
- он может начаться только после строки, которая кончается двоеточием;
- его строки сдвинуты вправо, принято на 4 пробела.
В программах из одних вызовов print строк с двоеточием нет, поэтому каждая строка начинается с первого символа. Лишний отступ интерпретатор находит при той же проверке файла и сообщает ошибку IndentationError.
Ошибка во время работы
Опечатку в имени функции проверка файла не замечает: правила записи не нарушены. Машина принимает лист и начинает печатать.
print("one") # one
print("two") # two
pritn("three") # ✗
print("four")NameError: name 'pritn' is not defined. Did you mean: 'print'?Давайте разберём, что происходит при запуске:
- Первая строка печатает
one. - Вторая строка печатает
two. - На третьей интерпретатор ищет функцию
pritn, не находит её и останавливает программу с ошибкойNameError. - Четвёртая строка уже не выполняется, и
fourне появляется.
Так ведёт себя любая ошибка, которую находит только выполнение. Строки выше неё уже отработали, и их вывод остаётся на ленте.
Как читать трассировку
Сообщение об ошибке занимает несколько строк и называется трассировкой. У ошибки из примера выше она устроена так:
Traceback (most recent call last):— заголовок: ошибка случилась во время работы.File "…/hello.py", line 3, in <module>— путь к файлу и номер строки с ошибкой.- Сама строка
pritn("three"), а под ней значки^, которые отмечают место ошибки. NameError: name 'pritn' is not defined. Did you mean: 'print'?— вид ошибки и причина.
Читайте трассировку с последней строки: она сразу говорит, что случилось. Номер строки из второй строки трассировки подскажет, где искать.
У ошибок, найденных при проверке файла, строки Traceback нет. Но последняя строка устроена так же: вид ошибки, двоеточие и причина.
Частая ошибка
Перед вызовом случайно оказался пробел:
print("one")
print("two") # ✗IndentationError: unexpected indentОдного пробела хватает: строка выше не кончается двоеточием и не открывает блок. Поэтому отступ во второй строке лишний. Ошибку находит проверка файла, поэтому не печатается даже one. Исправление — удалить пробелы в начале строки.
Главное
- Перед запуском интерпретатор проверяет весь файл, и ошибка записи —
SyntaxErrorилиIndentationError— не даёт выполниться ни одной строке. - Отступ открывает блок, а блок может начаться только после строки с двоеточием.
- Ошибка во время работы, например
NameError, останавливает программу на своей строке, и вывод строк выше уже напечатан. - Трассировку читают с последней строки: там вид ошибки и причина.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.