IndentationError: unexpected indent — ошибка Python, которая означает: строка начинается с отступа там, где новый блок не открывался. Чаще всего это лишние пробелы в начале строки после вставки кода из чата, PDF или другого файла. Исправление — убрать отступ или выровнять строку по уровню соседних строк того же блока.
Содержание
Ниже — как Python читает отступы, правила PEP 8, четыре ошибки отступов с реальным выводом и способ быстро найти проблемную строку. Все примеры и тексты ошибок проверены на Python 3.14.7 (сентябрь 2026).
Три понятия, которые путают
- Отступ (indentation) — пробелы или табуляция в начале строки. В Python это часть синтаксиса, а не оформление.
- Блок — группа строк с одинаковым отступом. Блок открывает строка с двоеточием в конце:
if,elif,else,for,while,def,class,with,try,except,finally,match,case. - Уровень отступа — глубина вложенности. Новый уровень глубже предыдущего; при выходе из блока строка должна вернуться точно на один из уже существующих уровней.
Там, где в C, Java или JavaScript блок ограничивают фигурные скобки, в Python его границы задает только отступ.
Как Python читает отступы: рабочий пример
numbers = [1, 2, 3]
for n in numbers:
if n % 2 == 0:
print(n, "even")
else:
print(n, "odd")
print("done")
Вывод:
1 odd
2 even
3 odd
done
Здесь три уровня: 0 пробелов (numbers, for, последний print), 4 пробела (if и else внутри цикла) и 8 пробелов (тела if и else). Строка print("done") вернулась на уровень 0, поэтому выполняется один раз после цикла. Сдвиньте ее на 4 пробела — и она окажется внутри цикла, done напечатается трижды. Ошибки не будет: интерпретатор не угадывает намерение, он просто читает структуру по отступам.
Внутри одного блока все строки обязаны иметь одинаковый отступ. Разные блоки технически могут использовать разную ширину (например, 8 пробелов), и код запустится, но это нарушает PEP 8.
Правила отступов по PEP 8
PEP 8 — официальное руководство по стилю кода Python. По отступам оно рекомендует:
| Правило | Что это значит на практике |
|---|---|
| 4 пробела на уровень | Каждый вложенный блок сдвигается на 4 пробела |
| Пробелы предпочтительнее табуляции | Табуляция допустима, только если весь существующий файл уже на табах |
| Не смешивать табы и пробелы | В Python 3 смешение, при котором смысл зависит от ширины таба, дает TabError |
| Продолжение строки в скобках | Выравнивание по открывающей скобке или «висячий» отступ; такие строки не создают блок |
Последний пункт важен: внутри круглых, квадратных и фигурных скобок Python не проверяет отступы продолжения строк. Код ниже рабочий, хотя выровнен некрасиво:
total = (1 +
2 +
3)
print(total)
Вывод: 6. То же касается комментариев: строка, в которой только #-комментарий, может иметь любой отступ и не вызывает ошибку. Пустые строки тоже игнорируются.
Точка с запятой и однострочная запись (if x > 3: print("big")) синтаксически допустимы, но PEP 8 не рекомендует составные операторы в одну строку.
Ошибка unexpected indent: причина и исправление
Неверный код — лишний отступ во второй строке:
price = 100
discount = 10
print(price - discount)
Результат запуска (python app.py):
File "/w/app.py", line 2
discount = 10
IndentationError: unexpected indent
Python видит отступ, но предыдущая строка не заканчивается двоеточием и блок не открывала. Номер строки в сообщении указывает на строку с лишним отступом.
Исправление — выровнять строку по соседям:
price = 100
discount = 10
print(price - discount)
Вывод: 90.
Типовые источники этой ошибки:
- Код скопирован из мессенджера, PDF или статьи, и в начале строк остались пробелы.
- Фрагмент перенесли из тела функции на верхний уровень файла, но не убрали отступ.
- Удалили строку
if ...:илиfor ...:, а ее тело осталось с отступом. - В консоль Python вставили код, первая строка которого начинается с пробелов.
Если ошибка указывает на первую строку файла — значит, первая строка с кодом начинается с пробела или таба. На верхнем уровне модуля отступа быть не должно.
Три соседние ошибки отступов
У unexpected indent есть «родственники». Сообщения похожи, но причина и исправление разные.
| Сообщение | Что не так | Как исправить |
|---|---|---|
unexpected indent |
Отступ есть, а блок не открывался | Убрать лишний отступ |
expected an indented block after ... |
Блок открыт двоеточием, но тела нет | Сдвинуть тело вправо или написать pass |
unindent does not match any outer indentation level |
Строка вернулась на уровень, которого не было | Выровнять по одному из внешних уровней |
TabError: inconsistent use of tabs and spaces |
В отступах смешаны табы и пробелы | Заменить табы на пробелы во всем файле |
expected an indented block
age = 20
if age >= 18:
print("adult")
File "/w/age.py", line 3
print("adult")
^^^^^
IndentationError: expected an indented block after 'if' statement on line 2
После if age >= 18: Python ждет строку глубже на один уровень. Исправление — сдвинуть print("adult") на 4 пробела. Если тело пока не написано, пишут pass: комментарий его не заменяет. Функция вида def process(): с одним комментарием внутри и без pass дает ту же ошибку: expected an indented block after function definition on line 1.
unindent does not match any outer indentation level
def total(items):
s = 0
for x in items:
s += x
return s
File "/w/total.py", line 5
return s
^
IndentationError: unindent does not match any outer indentation level
У return отступ 6 пробелов, а существующие уровни — 0, 4 и 8. Нужно выбрать, где должен быть return: 4 пробела — вернуть сумму после цикла (обычно это и нужно), 8 — внутри цикла, и функция вернет результат уже после первого элемента.
TabError
В строке 2 отступ 4 пробела, в строке 3 — один символ табуляции:
def f(flag):
if flag:
return 1
return 0
print(f(True))
File "/w/tabs.py", line 3
return 1
^
TabError: inconsistent use of tabs and spaces in indentation
В редакторе такой код часто выглядит ровно, потому что таб отображается как 4 или 8 пробелов. Python 3 не угадывает ширину таба и отказывается запускать код, если его смысл от нее зависит. Файл, где все отступы только табами, запустится, но PEP 8 для нового кода советует пробелы.
Отдельный случай — try без except/finally. Строка после тела try на том же уровне дает SyntaxError: expected 'except' or 'finally' block. Это не IndentationError, хотя возникает из-за расположения строк: после тела try на уровне try должны идти except или finally.
Как найти проблемную строку
- Прочитайте номер строки в сообщении. Для
unexpected indentпроблема именно в этой строке, дляexpected an indented block— в строке с двоеточием, указанной в тексте ошибки, и в следующей за ней. - Включите в редакторе отображение пробельных символов (whitespace). В VS Code и PyCharm табы и пробелы начнут различаться визуально.
- Проверьте файл без запуска:
python -m py_compile app.py. Для файла с лишним отступом команда выведетSorry: IndentationError: unexpected indent (app.py, line 2). - Для табов есть стандартный модуль
tabnanny:python -m tabnanny -v app.py. На файле со смешанными отступами он сообщает номер строки иinconsistent use of tabs and spaces in indentation, на чистом —Clean bill of health.
Если нужно проверить много файлов по правилу «только пробелы, кратно 4», хватит короткого скрипта:
import sys
def check_indent(path):
"""Печатает строки с табами и отступом не кратным 4 пробелам."""
with open(path, encoding="utf-8") as f:
for num, line in enumerate(f, start=1):
stripped = line.lstrip(" \t")
if not stripped.strip():
continue # пустые строки не проверяем
indent = line[: len(line) - len(stripped)]
if "\t" in indent:
print(f"{path}:{num}: табуляция в отступе {indent!r}")
elif len(indent) % 4:
print(f"{path}:{num}: отступ {len(indent)} пробелов, не кратно 4")
for p in sys.argv[1:]:
check_indent(p)
Запуск на файлах из примеров выше (python check.py total.py tabs.py):
total.py:5: отступ 6 пробелов, не кратно 4
tabs.py:3: табуляция в отступе '\t'
Скрипт упрощенный: строки продолжения внутри скобок и многострочные строки он проверяет так же строго, как обычный код, поэтому возможны лишние срабатывания. Для реальных проектов надежнее форматировщик.
Как не допускать ошибок отступов
- Настройте редактор: Tab вставляет 4 пробела. В VS Code и PyCharm для Python это поведение по умолчанию, но у файлов из чужих проектов редактор может подстроиться под уже найденные в файле табы. Уже существующие табы при сохранении сами не заменяются: их переводят в пробелы командой редактора (в VS Code — Convert Indentation to Spaces) или форматировщиком.
- Подключите форматировщик: Black, Ruff (
ruff format) или autopep8. Он приводит отступы к единому виду при запуске, а если включить форматирование при сохранении — при каждом сохранении. Файл с синтаксической ошибкой форматировщик обычно не исправит — сначала нужно убрать саму ошибку. - Вставленный код выравнивайте целиком: выделить фрагмент и сдвинуть блок (Shift+Tab в большинстве редакторов уменьшает отступ всех выделенных строк).
Выводы
- Отступ в Python — часть синтаксиса: он задает границы блока вместо фигурных скобок.
unexpected indent— лишний отступ в строке, перед которой блок не открывался; лечится выравниванием строки по соседям.expected an indented block,unindent does not matchиTabError— другие ошибки с другой причиной, их различают по тексту сообщения.- PEP 8: 4 пробела на уровень, пробелы вместо табов, без смешивания; внутри скобок отступы продолжения свободные.
- Для поиска помогают номер строки в ошибке, отображение пробелов в редакторе,
py_compile,tabnannyи форматировщик.
Где применяется / связь с практикой
Ошибки отступов — первое, с чем сталкивается почти каждый, кто начинает писать на Python: они появляются при копировании примеров, рефакторинге и работе с чужим кодом. Привычка держать единый стиль и читать сообщения интерпретатора экономит часы отладки уже на учебных задачах.
Освойте тему на практике
Базовый синтаксис, структуру программ, функции и работу с ошибками системно разбирают на курсе «Python-разработчик. Базовый уровень». Посмотреть формат занятий и задать вопросы преподавателям можно на открытых уроках Otus.
FAQ
Сколько пробелов нужно для отступа в Python?
Интерпретатору важно только одинаковое число пробелов внутри одного блока. PEP 8 рекомендует 4 пробела на уровень, и этого придерживается большинство проектов и форматировщиков.
IndentationError — это разновидность SyntaxError?
Да. IndentationError наследуется от SyntaxError, а TabError — от IndentationError. Поэтому ошибки отступов, как и синтаксические, обнаруживаются до выполнения первой строки программы.
Почему код работает в одном редакторе и падает после копирования?
Чаще всего при копировании появились табы или лишние пробелы в начале строк: их находят отображением пробельных символов, python -m tabnanny и форматировщиком. Отдельный случай — неразрывный пробел: он дает не IndentationError, а SyntaxError: invalid non-printable character U+00A0, и tabnanny его не замечает (на таком файле пишет Clean bill of health.). Лечится поиском символа U+00A0 в редакторе и заменой на обычный пробел.



