2.25. エラーの処理

Python における実行時の問題のほとんどは例外として現れます。これは何かがうまくいかなかったことを報告するための、名前付きで構造化された方法です。ValueErrorTypeErrorKeyErrorOSErrorMemoryError はすべてその例です。それぞれがクラスであり、例外を送出すると現在の呼び出しが停止し、周囲のコードからハンドラを探します。

2.25.1. try / except

コードのブロックを try で囲むことで、それが送出する任意の例外を捕捉します:

try:
    n = int(input_text)
except ValueError:
    n = 0

int(...) の変換が失敗すると、制御はエラーをさらに伝播させる代わりに except ブロックへ飛びます。input_text が有効な整数の文字列であれば、except ブロックはスキップされます。

1つの try は複数の except ブロックを持つことができ、それぞれが異なる種類のエラーを捕捉します:

try:
    value = data[key]
except KeyError:
    value = None
except TypeError:
    value = -1

Python は順番に照合し、例外クラスが適合した最初のものが問題を処理します。Exception(ほぼすべての基底クラス)を捕捉するとあらゆるエラーを処理しますが、これはクラッシュが唯一の代替手段となるプログラムの最も外側の層に限って使ってください。

警告

裸の except:(キーワードの後にクラスがないもの)は KeyboardInterrupt も捕捉します。これは実行中のスクリプトを中断するために IDE の停止ボタンを押したときに IDE が送る例外です。裸の except: pass で囲まれたループはこの中断を飲み込んで実行を続け、電源を入れ直す以外にスクリプトを止める方法がなくなります。

広く捕捉する必要が本当にある場合は、裸の except: よりも except Exception: を優先してください。KeyboardInterruptException ではなく BaseException を継承しているため、except Exception: では停止ボタンが機能し続けます。

2.25.1.1. 例外の調査

例外に付随するメッセージを読むには、as で名前を付けます:

try:
    f = open("data.txt")
except OSError as e:
    print("could not open file:", e)

as で束縛された変数は、except ブロックの内部でのみ有効です。

2.25.2. else と finally

try ブロックには2つの省略可能な追加要素があります。

elsetry が例外を送出せずに完了したときにのみ実行されます:

try:
    value = compute()
except ValueError:
    print("bad input")
else:
    print("got", value)

「うまくいったときに何をするか」を else に置くことで、try ブロックを狭く保てます。失敗する可能性のある行だけが try に属します。

finally は、try が成功したか、送出されて処理されたか、送出されてこれから伝播しようとしているかにかかわらず、何があっても最後に実行されます:

try:
    do_work()
finally:
    cleanup()
try / except / else / finally を通る4つの可能な経路を示すフロー図。 成功は else を経て finally へ進む。捕捉された例外は except を経て finally へ進む。捕捉されなかった例外は finally を経て 伝播する。

finally は常に実行されます。else は例外が発生しない経路でのみ実行されます。

ほとんどの取得/解放のパターンでは、try / finally の組み合わせよりも コンテキストマネージャ を優先してください。リソース自身が自分のクリーンアップを管理します。

2.25.3. よくある組み込み例外

よく遭遇する例外の短いリストです:

  • ValueError -- 型は正しいが値が間違っている(bytes([300]) -- 300 は正しい型だが、有効なバイト範囲 0..255 の外にある)。

  • TypeError -- そもそも型が間違っている(len(42))。

  • KeyError -- dict に存在しないキー。

  • IndexError -- シーケンスの末尾を越えたインデックス。

  • AttributeError -- 存在しない属性へのアクセス("abc".foo)。

  • OSError -- ファイルシステムまたは I/O の失敗。

  • MemoryError -- ヒープが尽きた。メモリに制約のあるランタイムでは、これは病的なケースだけでなく通常の動作中にも起こり得ます。