IndentationError: unexpected indent と expected an indented block の直し方[Python]
Pythonはブロックを字下げで表すので、字下げが合わないとその場で止まる。出るメッセージはいくつか種類があって、それぞれ意味が違う。
メッセージごとの意味
IndentationError: unexpected indent字下げが不要な場所で字下げしている。前の行が:で終わっていないのに、次の行が下がっている状態になる。
x = 1 y = 2 # unexpected indentIndentationError: expected an indented block字下げが必要な場所で字下げされていない。ifやfor、defのあとの行が下がっていない。
def f():print("hi") # expected an indented blockIndentationError: unindent does not match any outer indentation level字下げを戻したが、その深さがどの階層とも一致しない。3段下がっていたものを、中途半端な位置に戻したときに出る。
TabError: inconsistent use of tabs and spaces in indentationタブとスペースが混ざっている。これが最も見つけにくい。
タブとスペースの混在
見た目では区別がつかないので、原因として最も厄介になる。
Web上のコードをコピーするとタブが混ざる、エディタの設定が途中で変わる、複数人で書いている、といった状況で起きる。
見つけ方はいくつかある。エディタに不可視文字を表示させるのがいちばん早い。多くのエディタに「空白文字を表示」や「Render Whitespace」といった設定がある。
コマンドで探すこともできる。
grep -Pn "^\t" file.py # 行頭のタブを探すgrep -Pn "^ *\t" file.py # スペースの後のタブPythonに調べさせる方法もある。
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 blockpassを置く。
def todo(): passifやfor、class、tryでも同じになる。...も同じ用途で使える。
def todo(): ...条件分岐の中で字下げがずれる
長い関数の中で、意図せず階層が変わってしまうことがある。
for item in items: if item.ok: process(item) log(item) # unindent does not match any outer indentation levellogの位置が中途半端になっている。4スペース単位で揃える。
このタイプは、行番号がエラーに出るので、その行と前後の階層を見比べれば分かる。エディタの縦のガイド線を表示しておくと目視で気づきやすい。
再発を防ぐ設定
その場で直すより、環境側で防いだほうが早い。
・エディタでタブをスペースに自動変換する設定を入れる。VS Codeなら"editor.insertSpaces": trueと"editor.tabSize": 4
・保存時に整形するフォーマッタを入れる。blackやruff formatなら字下げは自動で揃う
・.editorconfigを置いて、チーム全体で設定を共有する
・不可視文字の表示を常時オンにしておく
.editorconfigの最小構成はこうなる。
[*.py]indent_style = spaceindent_size = 4📘 文法の基礎を一通りさらうなら、独習Python。
まとめ
・unexpected indentは下げる必要のない行が下がっている。expected an indented blockはその逆
・unindent does not matchは戻した位置がどの階層とも一致していない
・TabErrorはタブとスペースの混在。見た目で分からないので不可視文字を表示して探す
・空のブロックにはpassか...を置く
・標準はスペース4つ。プロジェクトで統一する
・エディタの自動変換とフォーマッタ、.editorconfigを入れれば再発しなくなる
※本記事にはアフィリエイト広告を含みます。