🙄

【Python】例外処理の使い分けについて:raise文、assert文、try-except文

2024/09/26に公開

はじめに

Pythonにおける例外処理は、プログラムの実行中に発生するエラーを適切に捕捉し、処理を継続したり、エラーの原因を特定したりするために不可欠な仕組みです。

raise文、assert文、try-except文という3つの主要な要素がありますが、これらをどのように使い分けるべきか、混乱する方も多いのではないでしょうか。

本記事では、これらの文法要素の役割を詳しく解説し、とくにraise文とassert文に、try-except文を使うべきかどうかという点について、具体的なコード例を交えて深堀りします。

raise文とは?

raise文は、プログラマが意図的に例外を発生させるために使用します。

raise ValueError("入力値が不正です")

のように、raiseの後に例外オブジェクトを渡すことで、その種類の例外が発生します。

この例外オブジェクトは、自作の例外クラスでも構いません。

assert文とは?

assert文は、ある条件が真であると仮定してプログラムを書き、その仮定が誤っていた場合に例外を発生させるためのアサーション(断言)です。

assert x > 0, "xは正の値でなければなりません"

のように、assertのあとに条件式と、条件が偽だった場合に表示されるメッセージを指定します。

assert文は、デバッグモードで実行されることが多く、本番環境では無効化されることが多いです。

ですので基本的には、raise文が使われることのほうが多いようです。

try-except文とは?

try-except文は、例外が発生する可能性のあるコードブロックをtryブロックで囲み、例外が発生した場合にexceptブロック内のコードを実行します。

try:
    result = 10 / 0
except ZeroDivisionError:
    print("ゼロで除算することはできません")
print("終わり")

ここで重要なのは、exceptの処理が実行されたあと、そこでプログラムが終わるのではなく、print("終わり")が実行されることです。

つまりtry-except文は、例外処理があった場合でもプログラムを終了させないためのものと考えられます。

また、exceptブロックでは、特定の例外の種類を指定することが可能です。

ここでは、すべての例外をキャッチするexcept Exceptionを使うこともできます。

その場合は、以下のように書きます。


except Exception:
    print("エラーが発生しました")

または、以下のように記載し、エラーメッセージを出力します。


except Exception as e:
    print(e.args)

また、try-except文には、以下のようにelsefinallyも存在します。

try:
    # 例外が発生する可能性のあるコード
except 例外の種類:
    # 例外が発生した場合の処理
else:
    # 例外が発生しなかった場合の処理
finally:
    # 必ず実行される処理

tryブロック: 例外が発生する可能性のあるコードを記述します。
exceptブロック: 特定の例外が発生した場合に実行されるコードを記述します。
elseブロック: 例外が発生しなかった場合に実行されるコードを記述します。
finallyブロック: 例外が発生したかどうかに関わらず、必ず実行されるコードを記述します。

try-except文のなかでraise文を使うべきか?

raise文は、プログラマが意図的に例外を発生させるためのものです。

一般的には、raise文自体をtry-except文で囲む必要はありません。

ただ、囲んでもOKです。

その場合、raise文は、通常、呼び出し元の関数でtry-except文でキャッチされるもののようです。

いまいちこれらの使い分けが分かっていないのですが、raiseだけだとTracebackでどこでエラーが発生したかも表示されてしまうので、raiseで指定したエラー文だけを表示させたい場合、そして、raise後も処理をつづけたい場合は、try-except文と合わせて使用するのだと思います。

def divide(x, y):
    try:
        if y == 0:
            raise ValueError("除数に0を指定することはできません")
        return x / y
    except ValueError as e:
        print(e)

ちなみに、exceptのなかでもraiseを使用する用法もありますが、詳しくは下記の他の方の記事を参考にしていだければと思います。

https://news.mynavi.jp/techplus/article/python-31/

try-except文のtry部分にassert文を含めるべきか?

assert文は、プログラムのロジック上のエラーを早期に検出するためのものです。

assert文で発生した例外は、通常、プログラムの重大な問題を示しており、try-except文でキャッチして処理を続けることは推奨されません。

ですので一般的には、assert文自体をtry-except文で囲むべきではないようです。

まとめ

  • raise文は、プログラマが意図的に例外を発生させる。
  • assert文は、プログラムのロジック上のエラーを検出するためのアサーション。
  • try-except文は、例外を捕捉し、処理を継続するための仕組み。
  • raise文は、通常、呼び出し元の関数でtry-except文でキャッチされる。
  • assert文は、try-except文でキャッチするのではなく、プログラムの修正を促すためのもの。

例外処理のベストプラクティス

  • 特定の例外をキャッチし、適切な処理を行う。
  • except Exceptionは、すべての例外をキャッチするため、安易に使うべきではない。
  • finallyブロックを使って、例外が発生しても必ず実行したい処理を記述する。

まとめると、raise文とassert文は、それぞれ異なる目的に使用されるものであり、try-except文との組み合わせ方にも注意が必要です。

本記事で解説した内容が、適切な例外処理を実装し、より堅牢なPythonプログラムを作るさいの参考になれば幸いです。

メモ

まだ読み込めていないのですが、例外処理を決める判断基準になりそうな記事を備忘録として貼っておきます。

https://qiita.com/TairaNozawa/items/ab878eaa0b9f64b9854f

https://python.ms/raise/#_1-具体例を見てみる。

Discussion