Kodokon kodokon.com

エラーと例外:try、except、raise

try/except/else/finallyで予測できる失敗を捕まえ、raiseで自分の例外を投げて不正なデータを知らせましょう。

9 分 · 3 問

このレッスンを Kodokon で開く

実際のプログラムは失敗します。ファイルがない、入力が不正、ネットワークが切れる。Pythonはこうした状況を例外で知らせます。例外は実行を中断し、try/exceptが捕まえるまで呼び出しスタックをさかのぼって伝わっていきます。実務での反射的な習慣は、できるだけ限定された例外を、どう対処すればよいか分かっている場所のできるだけ近くで捕まえることです。

PYTHON
def parse_age(text):
    try:
        return int(text)
    except ValueError:
        return None

print(parse_age("34"))      # 34
print(parse_age("thirty"))  # None
あらゆるエラーではなく、ValueErrorだけを正確に捕まえる

完全なブロックには四つの枝があります。tryには危険なコードを入れ、exceptが失敗を処理し、else例外が投げられなかったときだけ実行され、finallyどんな場合でも実行されます。資源を解放したり、ログを残したりするのにぴったりです。elseの要点は、tryを最小限に保つことです。そうすれば、どの行が失敗しうるのか一目でわかります。

PYTHON
values = ["10", "abc", "25"]
total = 0

for value in values:
    try:
        number = int(value)
    except ValueError:
        print(f"Skip : {value}")
    else:
        total += number
    finally:
        print(f"Process : {value}")

print(total)  # 35
elseはエラーがないときだけ実行され、finallyは常に実行される

あなたの関数も、raiseで自分の例外を投げることができます。受け取ったデータが不正だと分かったらすぐにです。間違った結果を作り出すより、はっきりしたメッセージですぐに失敗するほうがよいのです。Exceptionを継承した専用のクラスを定義しましょう。呼び出し元は、ほかのエラーをうっかり横取りすることなく、それだけを狙って捕まえられるようになります。

PYTHON
class EmptyCartError(Exception):
    pass

def checkout(items):
    if not items:
        raise EmptyCartError("Empty cart.")
    return round(sum(items), 2)

try:
    print(checkout([]))
except EmptyCartError as error:
    print(f"Error : {error}")
専用の業務例外は、失敗をはっきりと、的を絞って伝える

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. try/exceptのelseブロックはいつ実行されますか?
    • tryの中で例外が投げられなかったときだけ
    • 例外が捕まえられたときだけ
    • どんな場合でも、tryのあとに
  2. finallyブロックはどんな場合に実行されますか?
    • 例外が投げられたときだけ
    • 例外が投げられなかったときだけ
    • 例外があってもなくても、どんな場合でも
  3. すべてを捕まえるむき出しのexcept:を避けるべきなのはなぜですか?
    • 本当のバグを隠し、デバッグをとても難しくするから
    • 的を絞ったexceptより遅いから
    • 標準ライブラリの例外にしか効かないから