第8章: エラーとの付き合い方:例外処理

プログラムの実行中に予期せぬ問題が発生すると、Pythonは「例外 (exception)」を送出して処理を中断します。これらのエラーを放置するとプログラムはクラッシュしてしまいますが、「例外処理」の仕組みを使うことで、エラーを優雅に捉えて対処できます。この章では、その方法を学びます。

`try...except`による例外の捕捉

他の言語の try...catch と同様に、Pythonでは try...except ブロックを使います。エラーが発生する可能性のあるコードを try ブロックに記述し、エラーが発生した際の処理を except ブロックに記述します。

例えば、0 で割り算をすると ZeroDivisionError という例外が発生します。

このエラーを try...except で捕捉してみましょう。

try ブロック内で ZeroDivisionError が発生したため、プログラムはクラッシュせずに except ブロック内の処理が実行されました。

複数の例外を処理する方法

try ブロック内では、複数の種類のエラーが発生する可能性があります。例えば、ユーザーの入力を数値に変換しようとして失敗した場合は ValueError が発生します。

複数の例外を処理するには、2つの方法があります。

1. except ブロックを複数記述する

エラーの種類ごとに異なる処理を行いたい場合に適しています。

2. 1つの except ブロックでタプルを使ってまとめる

複数の例外に対して同じ処理を行いたい場合に便利です。

as e のように書くことで、発生した例外オブジェクトそのものを変数 e で受け取ることができます。これにより、具体的なエラーメッセージを表示できます。

独自例外の送出 (`raise`)

特定の条件を満たした場合に、意図的に例外を発生させたいことがあります。その場合は raise 文を使います。

例えば、負の値を受け付けない関数を考えてみましょう。

このように、raise を使うことで、関数の事前条件などを満たさない場合に、プログラムの実行を中断して呼び出し元にエラーを通知できます。

`else`と`finally`節の役割

try...except ブロックには、elsefinally という2つのオプションの節を追加できます。

  • else: try ブロックで例外が発生しなかった場合にのみ実行されます。
  • finally: 例外の有無に関わらず、必ず最後に実行されます。ファイルクローズやデータベース接続の切断など、後片付け処理に最適です。

すべての節を使った例を見てみましょう。

この例から、実行フローが明確にわかります。

  • 成功ケースでは try -> else -> finally の順に実行されます。
  • 失敗ケースでは try -> except -> finally の順に実行されます。

finally 節は、try ブロック内で return が実行される場合でも、その return の直前に実行されることが保証されています。これにより、リソースの解放漏れなどを防ぐことができます。

この章のまとめ

この章では、Pythonにおけるエラー処理の基本を学びました。重要なポイントを振り返りましょう。

  • 例外: Pythonでは、エラーは「例外」オブジェクトとして扱われます。例外が発生すると、プログラムの実行は中断されます。
  • try...except: 例外が発生する可能性のあるコードを try ブロックで囲み、except ブロックで捕捉することで、プログラムのクラッシュを防ぎ、エラーに応じた処理を実行できます。
  • 複数の例外処理: except ブロックを複数記述したり、タプルでまとめたりすることで、さまざまな種類のエラーに柔軟に対応できます。
  • raise: 特定の条件で意図的に例外を発生させ、プログラムに異常な状態を通知します。
  • elsefinally: try ブロックが成功した場合の処理を else に、成功・失敗にかかわらず必ず実行したい後片付け処理を finally に記述することで、より堅牢なコードを書くことができます。

例外処理をマスターすることは、予期せぬ入力や状況に強い、安定したプログラムを作成するための重要なステップです。

練習問題1: 安全なリスト要素の取得

リストとインデックスを受け取り、そのインデックスに対応する要素を返す safe_get(my_list, index) という関数を作成してください。

要件:

  1. インデックスがリストの範囲外の場合 (IndexError)、「指定されたインデックスは範囲外です。」と表示してください。
  2. インデックスが整数でない場合 (TypeError)、「インデックスは整数で指定してください。」と表示してください。
  3. 正常に要素を取得できた場合は、その要素を返してください。
practice8_1.py
python practice8_1.py

練習問題2: ユーザー年齢の検証

ユーザーの年齢を入力として受け取り、18歳以上であれば「あなたは成人です。」と表示する check_age(age_str) という関数を作成してください。

要件:

  1. 関数内部で、受け取った文字列を整数に変換してください。変換できない場合 (ValueError) は、ValueErrorraise して、「有効な数値を入力してください。」というメッセージを伝えてください。
  2. 変換した数値が負の値である場合、ValueErrorraise して、「年齢に負の値は指定できません。」というメッセージを伝えてください。
  3. 年齢が0歳から17歳までの場合は、「あなたは未成年です。」と表示してください。
  4. 関数の呼び出し側で、raise された例外も捕捉できるようにしてください。
practice8_2.py
python practice8_2.py