例外処理とは?
例外処理とは、プログラムの実行中に起きたエラーに対応するための仕組みです。失敗するかもしれないコードを try などの保護されたブロックに入れておくと、エラーが発生したときにクラッシュする代わりに、except や catch などのハンドラに制御が移ります。
更新日: 2026年9月24日
年齢を尋ねるプログラムは、いつか20ではなく「twenty」を受け取ることになります。このテキストの変換は実行時エラーです。int("twenty") は ValueError を発生させ、何の備えもなければプログラムは停止します。例外処理とは、その備えのことです。失敗するかもしれないコードに印を付け、失敗したときに実行するコードを書いておきます。
Next year you will be 35
Not a number: twenty
Next year you will be 20
Done
おかしな回答は報告され、ループは次の回答へと進みます。try がなければ、プログラムは1行表示した後にトレースバックを出して終わっていたでしょう。
例外処理の仕組み
tryの中のコードは通常どおり実行されます。- ある処理が失敗し、ランタイムが例外を発生させます。例外は、種類(
ValueError)とメッセージ(invalid literal for int() with base 10: 'twenty')を持つオブジェクトです。 tryブロックはその行で止まり、残りの行は飛ばされます。「twenty」のときに「Next year you will be」が表示されないのはこのためです。- ランタイムは、例外の種類を上から順に各
except節と比べ、最初に一致したものを実行します。 - ハンドラが終わると、プログラムは
try文全体の次の行から処理を続けます。 - 一致する節がなければ、例外は現在の関数を抜け出し、その関数を呼び出した関数、さらにその呼び出し元へと探索が続きます。これをコールスタックの巻き戻しと呼びます。一致するものがないままプログラムの最上位まで到達すると、プログラムはトレースバックを出して終了します。
ステップ6から分かるように、ハンドラはエラーが起きた関数の中にある必要はありません。次の例では2段階深い呼び出しの中で失敗していますが、いちばん下のハンドラがそれを捕捉します。
parsing 4.50
parsing free
Could not add the prices: could not convert string to float: 'free'
float("free") は parse_price の中で失敗しました。parse_price にも total にもハンドラがなかったので、どちらも途中で放棄され、「3.20」は解析されませんでした。これが例外処理のもたらす設計上の大きな選択肢です。エラーは、それにどう対処すべきかが分かっている場所で処理します。そしてその場所は、エラーが起きた場所から遠く離れていることがよくあります。
try、except、else、finally
Pythonの try 文には、省略できる部分がさらに2つあります。else は、try ブロックが例外なしで終わったときだけ実行されます。finally はどの場合でも実行されます。成功した後でも、例外を処理した後でも、さらに try の中から関数が戻るときでもです。
no error
finally runs either way
2.0
b was zero
finally runs either way
None
finally には後片付けを書きます。ファイルを閉じる、ロックを解放する、データベースの接続を閉じる、といった処理です。Pythonでは、ファイルについては with 文がこの後片付けを自動で行ってくれるので、ふつうはそちらを使います。
自分で例外を発生させる
例外は、言語が検出するエラーのためだけのものではありません。自分の関数が扱えない入力を受け取ったとき、例外を発生させて処理を断り、次にどうするかを呼び出し元に決めさせることができます。小さな例外クラスを定義すると、エラーの内容を表す名前を付けられます。
70
Refused: cannot take 250, balance is 100
Pythonでは raise を使います。Java、C++、JavaScriptでは、同じことに throw を使います。
ほかの言語の例外処理
| 言語 | キーワード | 知っておきたいこと |
|---|---|---|
| Python | try、except、else、finally、raise | すべての例外は BaseException を継承したオブジェクト |
| Java | try、catch、finally、throw、throws | IOException のようなチェック例外は、捕捉するか throws で宣言しなければならない |
| C++ | try、catch、throw | finally はなく、スタックの巻き戻し時にデストラクタが後片付けをする |
| JavaScript | try、catch、finally、throw | async のコードのエラーは、await を try で囲んで捕捉する |
| C | なし | 関数はエラーコードを返し、多くは errno を設定する |
| Go | 通常のエラーにはなし | 関数が error の値を返し、呼び出し元がそれをチェックする |
同じ解析の例をJavaで書くと次のようになります。
try {
int age = Integer.parseInt("twenty");
System.out.println(age + 1);
} catch (NumberFormatException e) {
System.out.println("Not a number: " + e.getMessage());
} finally {
System.out.println("done");
}
Javaは例外を2つのグループに分けています。IOException のようなチェック例外は、プログラムの管理外で起きる問題を表し、捕捉も宣言もしないコードはコンパイラがビルドを拒否します。NullPointerException のような RuntimeException のサブクラスである非チェック例外は、たいていバグを意味し、コンパイラは処理を強制しません。
よくある間違い
- 何でも捕捉する。 Pythonの素の
except:はKeyboardInterruptまで捕捉してしまうので、Ctrl+Cが効かなくなります。またexcept Exception:は、想定していなかったバグまで捕まえます。対処方法が分かっている特定の種類を捕捉してください。 - エラーを握りつぶす。
except ValueError: passは問題を隠してしまいます。少なくとも、何が起きたかを表示するかログに記録してください。 tryブロックが大きすぎる。 捕捉しようとしている例外を発生させる可能性のある行だけを囲みます。そうすれば、無関係なエラーを誤って処理してしまうことがありません。- バグを直さずに捕捉する。 1回多く回るループから出た
IndexErrorは、コードの誤りです。それを処理してしまうと、間違ったコードが生き残り続けます。 - CやC++で
catchがクラッシュを止めてくれると期待する。 セグメンテーション違反は例外ではなくオペレーティングシステムからのシグナルなので、LinuxやmacOSではC++のcatch (...)がそれを受け取ることはありません。
次に読むページ
例外処理が対応するエラーについては実行時エラーのページで、例外処理では捕捉できないクラッシュについてはセグメンテーション違反のページで説明しています。構文の詳細は、Pythonの例外、Javaのtryとcatch、C++の例外、JavaScriptのtryとcatchのガイドを読んでください。JavaコースとPythonコースでは、どちらも実際の問題でこれらを練習できます。
よくある質問
Javaの例外処理の5つのキーワードは?
try、catch、finally、throw、throws です。try は監視するコードを示し、catch は特定の種類の例外を処理し、finally は例外が起きたかどうかに関係なく後片付けのコードを実行します。throw は例外を発生させ、メソッドのシグネチャに書く throws は、そのメソッドが呼び出し元に渡す可能性のあるチェック例外を宣言します。C++の例外処理とは?
try、catch、throw を使います。どんな型でも投げられますが、慣習として std::runtime_error のような std::exception の派生クラスのオブジェクトを投げ、catch (const std::exception& e) のように参照で受け取ります。C++には finally がなく、後片付けはデストラクタで行います。デストラクタはスタックが巻き戻される際に自動で実行されます。エラーと例外の違いは?
Exception はプログラムが対処できる問題を表し、OutOfMemoryError や StackOverflowError のような Error は、ふつうプログラムが捕捉しようとすべきでないJVMの障害を表します。Pythonでは、名前に反して ValueError も ZeroDivisionError も例外です。Javaのthrowとthrowsの違いは?
throw は、その場所で例外を1つ発生させる文です(throw new IllegalArgumentException("negative age");)。throws はメソッド宣言の一部で、そのメソッドが呼び出し元に渡す可能性のあるチェック例外を並べます(void load() throws IOException)。するとコンパイラは、すべての呼び出し元に対して、その例外を捕捉するか、自分でも宣言するかを求めます。例外処理を使うとコードは遅くなりますか?
try ブロックに入ること自体のコストは小さいです。Python 3.11以降、例外が発生しなければ try のコストはほぼゼロで、主要なC++コンパイラも、何も投げられない経路には実行時のコストを追加しません。ただし、例外を発生させて捕捉するのは if による判定よりずっと遅いので、性能が重要なループでは、例外に頼らずよくあるケースを事前にチェックしてください。