Tech カテゴリのイメージ

IndentationError: unexpected indent と expected an indented block の直し方[Python]

Pythonはブロックを字下げで表すので、字下げが合わないとその場で止まる。出るメッセージはいくつか種類があって、それぞれ意味が違う。

メッセージごとの意味

IndentationError: unexpected indent

字下げが不要な場所で字下げしている。前の行が:で終わっていないのに、次の行が下がっている状態になる。

x = 1
y = 2 # unexpected indent
IndentationError: expected an indented block

字下げが必要な場所で字下げされていない。iffordefのあとの行が下がっていない。

def f():
print("hi") # expected an indented block
IndentationError: unindent does not match any outer indentation level

字下げを戻したが、その深さがどの階層とも一致しない。3段下がっていたものを、中途半端な位置に戻したときに出る。

TabError: inconsistent use of tabs and spaces in indentation

タブとスペースが混ざっている。これが最も見つけにくい。

タブとスペースの混在

見た目では区別がつかないので、原因として最も厄介になる。

Web上のコードをコピーするとタブが混ざる、エディタの設定が途中で変わる、複数人で書いている、といった状況で起きる。

見つけ方はいくつかある。エディタに不可視文字を表示させるのがいちばん早い。多くのエディタに「空白文字を表示」や「Render Whitespace」といった設定がある。

コマンドで探すこともできる。

Terminal window
grep -Pn "^\t" file.py # 行頭のタブを探す
grep -Pn "^ *\t" file.py # スペースの後のタブ

Pythonに調べさせる方法もある。

Terminal window
python -t script.py # 警告を出す(古いバージョン)
python -X dev script.py

まとめて直すなら、エディタの「タブをスペースに変換」機能を使う。VS CodeならコマンドパレットからConvert Indentation to Spacesになる。

Pythonの標準的な流儀はスペース4つになる。プロジェクト全体で統一しておくのが前提になる。

コピペで崩れる

ブログやドキュメントからコピーすると、先頭に余分な空白が入ることがある。とくにプロンプト記号やコメントが混じった状態のコードは崩れやすい。

貼ったあとに、その範囲を選択して字下げをやり直すのが確実になる。多くのエディタでTabとShift+Tabによる一括の字下げができる。

Jupyterでセルを分割したときや、対話シェルに複数行を貼ったときも同じことが起きる。対話シェルには、貼り付け用のモードを持つものがある。

空のブロックを書きたいとき

処理を後回しにしたいのに、中身が空だとエラーになる。

def todo():
# expected an indented block

passを置く。

def todo():
pass

ifforclasstryでも同じになる。...も同じ用途で使える。

def todo():
...

条件分岐の中で字下げがずれる

長い関数の中で、意図せず階層が変わってしまうことがある。

for item in items:
if item.ok:
process(item)
log(item) # unindent does not match any outer indentation level

logの位置が中途半端になっている。4スペース単位で揃える。

このタイプは、行番号がエラーに出るので、その行と前後の階層を見比べれば分かる。エディタの縦のガイド線を表示しておくと目視で気づきやすい。

再発を防ぐ設定

その場で直すより、環境側で防いだほうが早い。

・エディタでタブをスペースに自動変換する設定を入れる。VS Codeなら"editor.insertSpaces": true"editor.tabSize": 4
・保存時に整形するフォーマッタを入れる。blackやruff formatなら字下げは自動で揃う
.editorconfigを置いて、チーム全体で設定を共有する
・不可視文字の表示を常時オンにしておく

.editorconfigの最小構成はこうなる。

[*.py]
indent_style = space
indent_size = 4

📘 文法の基礎を一通りさらうなら、独習Python

まとめ

unexpected indentは下げる必要のない行が下がっている。expected an indented blockはその逆
unindent does not matchは戻した位置がどの階層とも一致していない
TabErrorはタブとスペースの混在。見た目で分からないので不可視文字を表示して探す
・空のブロックにはpass...を置く
・標準はスペース4つ。プロジェクトで統一する
・エディタの自動変換とフォーマッタ、.editorconfigを入れれば再発しなくなる

※本記事にはアフィリエイト広告を含みます。