例外処理はプログラム実行中に起こり得るエラーを検知しそれを適切に処理するための重要な仕組みです。Pythonでは、この例外処理を実装するためにtry-except構文を用います。

このページではプログラミング初心者の方向けに、そもそも例外処理って何?というところから、例外処理の実装方法(try-except)について端的に解説します。
Pythonエンジニアを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。
Python:2つのエラー

はじめに、このページの前提となる内容「エラーの基本的な概念とPythonにおけるエラーの種類」について説明します。
Pythonにおけるエラーをより初心者向けに嚙み砕いて説明すると、「プログラムが期待される動作を遂行できない状況」ということができます。そして、これらのエラーは一般的に二つの大きなカテゴリーに分けることができます。それが構文エラー(Syntax Errors)と例外(Exceptions)です。
Python:構文エラー(syntax error)
プログラムがPythonの言語ルールに従っていない場合に発生します。

つまり、プログラムがPythonとして正しく書かれていないことを意味します。Python初心者から上級者までが必ず1日1回は遭遇するエラーかもしれません。
構文エラーは、プログラムが実行される前の解析段階で検出されます。例えば、閉じられていない括弧や、インデントが不適切な場合などがこれに該当します。
print("Hello World" # print関数の閉じ括弧が抜けています。
# 結果 ⇒ SyntaxError: unexpected EOF while parsing
Python:例外(exception)
例外(exception)は、プログラムが正しいPythonのコードルールを満たしていても、実行中に遭遇する可能性のあるエラーを表します。

例えば、ファイルが見つからない(FileNotFoundError)、リストの範囲外のインデックスへのアクセス(IndexError)、未定義の変数へのアクセス(NameError)などがこれに該当します。
代表的なものが「0で割る」場合に起きる「ZeroDivisionError」です。
def calc(a,b):
return a / b
calc(5,0) # 5÷0 を実施
# 結果 ⇒ ZeroDivisionError: division by zero
このようなエラーが発生した時、Pythonは通常プログラムを停止し、エラーメッセージを表示します。このエラーメッセージには、エラーの種類とエラーが発生した場所、そしてエラーの原因についての情報が含まれています。

例外処理というのは、これらのエラーを適切に処理し、プログラムにエラーが発生しても停止することなく、適切に動作を続けるための仕組みを導入すること。これが例外処理の主な目的であり、Pythonではtry-except構文がこのために用いられます。
ValueError(不適切な型や値に対する操作を行ったときに発生)
try:
# int関数は整数を表す文字列を引数に取るが、整数を表さない文字列を与えるとValueErrorが発生する
i = int("abc")
except ValueError:
print("ValueErrorが発生しました。") TypeError(互換性のない型間で操作を行ったときに発生します)
try:
# 文字列と数値の足し算はTypeErrorを発生させる
result = "abc" + 1
except TypeError:
print("TypeErrorが発生しました。") 参考 算術演算子
IndexError(シーケンスの範囲外のインデックスにアクセスしようとしたときに発生)
try:
# リストの範囲外のインデックスにアクセスするとIndexErrorが発生する
l = [1, 2, 3]
value = l[5]
except IndexError:
print("IndexErrorが発生しました。") 参考 リスト
KeyError(辞書に存在しないキーを参照しようとしたときに発生)
try:
# 辞書に存在しないキーを参照するとKeyErrorが発生する
d = {"apple": 1, "banana": 2}
value = d["orange"]
except KeyError:
print("KeyErrorが発生しました。") 参考 辞書(ディクショナリ)
FileNotFoundError(存在しないファイルを開こうとしたときに発生)
try:
# 存在しないファイルを開くとFileNotFoundErrorが発生する
f = open("nonexistent_file.txt")
except FileNotFoundError:
print("FileNotFoundErrorが発生しました。")Python:try-except
例外処理は、「もし例外が発生したら、〇〇する。」というように、あらかじめ例外が発生する可能性に備えてコーディングしておくことを指し示します。
Pythonのtry-except構文は、プログラムで発生可能なエラー(例外)をキャッチし、その場で適切な処理を行うためのもの。基本的なtry-exceptの構文は以下のようになります。
try:
# ここにはエラーが発生する可能性のあるコードを書きます
except エラーの種類: # ここにはキャッチしたいエラーの種類を書きます
# ここにはエラーが発生したときの処理を書きます
try:の次の行から、エラーが発生する可能性のあるコードを書きます。この部分をtryブロックと呼びます。例えば、存在しないファイルを開こうとするコードなどが該当します。
except エラーの種類:の部分では、キャッチしたいエラーの種類を指定します。例えば、FileNotFoundErrorやValueErrorなどです。指定したエラーがtryブロック内で発生すると、それをキャッチしてexceptブロックのコードが実行されます。

exceptブロックの中には、エラーが発生したときの処理を書きます。例えば、エラーメッセージを出力したり、代替の処理を行ったりします。具体的なコード例を見てみましょう。
try:
num = int(input("数値を入力してください: "))
except ValueError:
print("エラー:数値を入力してください!")
このコードでは、ユーザーからの入力を整数に変換しています。もしユーザーが数値でない文字列を入力した場合、int()関数はValueErrorを発生させます。これをexceptでキャッチし、適切なエラーメッセージを出力しています。

このように、try-except構文を使うと、エラーをキャッチして適切に処理することができ、プログラムのクラッシュを防ぐことができます。
Python:exceptブロックで例外を指定しない場合
exceptブロックで具体的な例外を指定せずに使用すると、tryブロック内で発生した全ての種類の例外をキャッチすることができます。
この方法は、発生する例外の種類が不明な場合や、全ての例外を同じように処理したい場合に便利です。

以下に、例外の種類を指定しないtry-except構文の使用例を示します。
try:
# エラーが発生する可能性のあるコード
num = int(input("数値を入力してください: "))
result = 10 / num
except:
# 全てのエラーに対する処理
print("エラーが発生しました!")
このコードでは、ユーザーが数値を入力することを求めています。ユーザーが数値以外の文字列を入力した場合、int()関数はValueErrorを。ユーザーが0を入力した場合、10 / numの計算はZeroDivisionErrorを発生させます。

上記のサンプルコードでは、これらのどちらのエラーもexceptブロックでキャッチされ、エラーメッセージが出力されることになります。
ただし、可能な限り具体的な例外を指定することが推奨されます。例外の種類を指定しないexceptブロックは全ての例外をキャッチしますが、どの種類のエラーが発生したか、そのエラーがなぜ発生したかを特定することが難しくなる可能性があるためです。
Python:exceptブロックで復習の例外を指定する場合
exceptブロックでは、複数の例外を一度に指定してキャッチすることが可能です。それらはタプル形式(丸括弧内にコンマで区切られた例外名)で指定します。これは、複数の異なるエラーが発生する可能性があるコードに対して、それぞれのエラーについて同じように処理をしたい場合に便利です。
参考 タプルとは?

以下に、複数の例外をキャッチするtry-except構文の使用例を示します。
try:
# エラーが発生する可能性のあるコード
num = int(input("数値を入力してください: "))
result = 10 / num
except (ValueError, ZeroDivisionError):
# 複数のエラーに対する処理
print("無効な入力です!")
このコードでは、ユーザーからの入力を整数に変換し、その数値で10を割っています。もしユーザーが数値でない文字列を入力した場合、int()関数はValueErrorを発生させます。また、ユーザーが0を入力した場合、10 / numの計算はZeroDivisionErrorを発生させます。

これらのどちらのエラーもexceptブロックでキャッチされ、エラーメッセージが出力されます。
このように、exceptブロックで複数の例外を指定することで、異なる種類のエラーに対して一貫したエラー処理を行うことができます。
応用:それぞれの例外に対して異なるexceptブロックを適用
特定の例外をハンドリングするためには、それぞれの例外に対して異なるexceptブロックを用意します。これにより、例外の種類に応じて異なる処理を実行することができます。
これは、エラーの種類ごとに適切なフィードバックを提供したり、特定のエラーに対する独自の対策を講じたりする場合に特に有用です。

以下に、複数の例外をそれぞれ異なるexceptブロックで処理するコード例を示します。
try:
num = int(input("数値を入力してください: "))
result = 10 / num
except ValueError:
print("無効な入力です。数値を入力してください。")
except ZeroDivisionError:
print("0で割ることはできません。他の数値を入力してください。")
このコードでは、ユーザーからの入力を整数に変換しその数値で10を割っています。
もしユーザーが数値でない文字列を入力した場合 →int()関数はValueErrorを発生させます。
ユーザーが0を入力した場合、10 / numの計算 →ZeroDivisionErrorを発生させます。

これらのエラーはそれぞれのexceptブロックでキャッチされ、それぞれのエラーに適したエラーメッセージが出力されます。
Python:else / finally
Pythonの例外処理構文には、tryとexceptの他にelseとfinallyというキーワードも含まれます。それぞれの使用法を説明します。
elseブロック
elseブロックはtryブロックのコードがエラーなく実行された場合に実行されるコードを記述します。すなわち、tryブロックが例外を引き起こさなかったときにのみ実行されます。

以下に、try-except-else構文の使用例を示します。
try:
num = int(input("数値を入力してください: "))
except ValueError:
print("無効な入力です。数値を入力してください。")
else:
print("入力された数値: ", num)
このコードでは、まずユーザーからの入力を整数に変換しようとしています。もしユーザーが数値でない文字列を入力した場合、int()関数はValueErrorを引き起こし、exceptブロックが実行されます。しかし、ユーザーが正しく数値を入力した場合、tryブロックは例外を引き起こさず、elseブロックが実行されます。
finallyブロック
finallyブロックは、tryブロックのコードがエラーを引き起こすかどうかに関わらず、最終的に実行されるコードを記述します。つまり、エラーが発生しようがしまいが、finallyブロック内のコードは必ず実行されます。

以下に、try-except-finally構文の使用例を示します。
try:
num = int(input("数値を入力してください: "))
except ValueError:
print("無効な入力です。数値を入力してください。")
finally:
print("入力処理が終了しました。")
このコードでは、最初の処理は前述の例と同じです。しかし、finallyブロックにより、「入力処理が終了しました。」というメッセージは、ユーザーが何を入力しようとも必ず表示されます。

これらのブロックを組み合わせて使用することで、様々な状況に対応した詳細なエラーハンドリングを実装することができます。
try:
# 例外が発生しうる処理
except (例外):
# 例外発生時の処理
else:
# 例外が発生しなかった場合の処理
finally:
# 最後に必ず実行される処理サンプル else / finally
def funny_division(divider):
try:
return 100 / divider
except ZeroDivisionError:
print("おっと!0で割ることはできません。")
except TypeError:
print("数値が必要です。")
else:
print("割り算がうまくいきました!")
finally:
print("私の仕事は終わりました。")
print(funny_division(50))
print(funny_division(0))
print(funny_division('hello'))
このコードは、数値を引数として受け取り、その数値で100を割ろうとする関数funny_division()を定義しています。
- 最初に
tryブロックが実行され、100を引数で割ろうとします。この時点で例外が発生する可能性があります。 ZeroDivisionErrorが発生した場合(例えば、引数が0の場合)、最初のexceptブロックが実行され、エラーメッセージが表示されます。TypeErrorが発生した場合(例えば、引数が数値でない場合)、次のexceptブロックが実行され、別のエラーメッセージが表示されます。tryブロックが成功した場合(例えば、引数が50の場合)、すなわち例外が発生しなかった場合、elseブロックが実行され、成功メッセージが表示されます。- 最後に、
finallyブロックが実行されます。これはtryブロックが成功したか失敗したかに関係なく、常に実行されます。この例では、完了メッセージが表示されます。

各ケースでどのように動作するかをしっかり理解しておきましょう。
Pythonを1から学習したい方は

始めてPythonを勉強するのは結構難しいですよね。
でもその悩みを抱えているのは一人じゃありません。全てのPython使いが同じ道を進んできました。
Pythonをはじめとするプログラミングスキルを武器に、時間と場所に捉われない自由な生き方を目指してみませんか?今すぐ行動したい方は以下の記事をチェック!
読者料典 Python入門:学習カリキュラム ←こちらから!
