プログラム実行時に、実行を妨げる異常な事象が発生した際、プログラムに「例外」として通知する機能があります
プログラムが「例外」に対処していない場合は、プログラムは異常終了してしまいますが、「例外」に対処していれば、通常の処理に戻ることができます
この章では「例外」に対処する処理である「例外処理」について説明をしていきます
例外を捉える
以下のようなプログラムを実行した場合、辞書のキーが存在しないというエラーが発生しプログラムが異常終了してしまいます
dc = {'ja':'japanease','en':'English','ch':'Chinese'}
print(dc['ja'])
print(dc['fr'])

そこで、異常終了しないように例外処理を書いてみたいと思います
Pythonで例外処理を捕捉するにはtry(トライ)文を使い以下のように記述します
try文を使うと本来の処理の流れを分断することなく、簡潔にエラー処理を書くことができます
try:
文
except 例外:
文
try:の後、改行し、例外が発生する可能性のある文を記述します
exceptの後には、例外処理の対象となる例外クラスを指定し、改行後、例外処理を記述します
上の例ではKeyErrorが発生していましたので、KeyErrorを捕捉してみます
dc = {'ja':'japanease','en':'English','ch':'Chinese'}
try:
print(dc['ja'])
print(dc['fr'])
except KeyError:
print("辞書のキーが見つかりません")
実行結果
japanease
辞書のキーが見つかりません
また、except節において except KeyError as e:と書くことで、例外オブジェクトを変数eで受け取ることもできます
dc = {'ja':'japanease','en':'English','ch':'Chinese'}
try:
print(dc['ja'])
print(dc['fr'])
print(dc['en'])
except KeyError as e:
print("辞書のキーが見つかりません"+str(e))
実行結果
japanease
辞書のキーが見つかりません:'fr'
変数eを表示してみると、例外処理をしていなかった最初のプログラムにおけるプログラム終了時に表示されていたエラーメッセージと同じものが表示されます
except節は以下のサンプルプログラムのように複数記述することもできます
try:
sum_price = int(input("合計金額を入力してください:"))
count = int(input("数量を入力してください:"))
price = sum_price // count
print("単価="+str(price))
except ValueError as e:
print("合計金額と数量は整数で入力してください")
print(e)
except ZeroDivisionError as e:
print("数量は0以外の整数で入力してください")
print(e)

合計金額に整数ではない値を入力した場合、ValueErrorが発生していることが確認できます

数量に0を入力した場合、ZeroDivisionErrorが発生していることが確認できます
また、あらゆる例外を処理したい場合にはExceptionという例外を指定することができます
Exceptionは大部分の例外クラスの基底クラスです
そのため、Exceptionから派生した例外クラスに対しては有効です
try:
sum_price = int(input("合計金額を入力してください:"))
count = int(input("数量を入力してください:"))
price = sum_price // count
print("単価="+str(price))
except Exception as e:
print("エラーが発生しました")
print(e)


例外クラスについては、Pythonの公式ドキュメントに記載されていますので参考にしてみてください
https://docs.python.org/ja/3/library/exceptions.html
例外を意図的に発生させる
「例外を捉える」では、例外を捉え処理する方法を説明してきました
一方、例外を意図的に発生させることもできます
raise 例外
raise文を使い例外を発生させます
例外の部分には発生させたい例外クラスや例外オブジェクトを指定することにより、エラーに関する情報を提供することができます
raise文は、try-exceptブロック内で使用することで、例外を捕捉して処理することができます
以下にraise文を使ったサンプルプログラムを示します
- Exceptionを発生させる
このサンプルプログラムは、my_functionの引数が負の値の場合、例外を発生させています
def my_function(value):
if value < 0:
raise Exception("値は0以上である必要があります")
# 処理を続行
try:
my_function(-1)
except Exception as e:
print("エラーが発生しました:" + str(e))
実行結果
エラーが発生しました: 値は0以上である必要があります
raise Exception("値は0以上である必要があります")
この行で、例外を発生させ、例外の内容を例外オブジェクトに格納しています
- 組み込みの例外も捕捉する
def divide(x, y):
if y < 0:
raise Exception("正の整数を指定してください")
return x / y
try:
result = divide(10, -1)
except ValueError as e:
print("エラーが発生しました: " + str(e))
except ZeroDivisionError as e:
print("エラーが発生しました: " + str(e))
except Exception as e:
print("エラーが発生しました: " + str(e))
実行結果
エラーが発生しました: 正の整数を指定してください
このサンプルでは複数の例外を捕捉しています
except節は上から順に処理をするので、Exceptionを上に記載すると、Exceptionの派生クラスであるValueErrorやZeroDivisionErrorもExceptionで処理されていまいます
そのためExceptionは一番下に記述しています
raise Exception("正の整数を指定してください")
divide関数は引数yが負の値を受け付けないようにするため、独自のエラーを発生させるようにしています
- 例外クラスを独自に定義する
class MyError(Exception):
pass
def my_function(value):
if value < 0:
raise MyError("値は0以上である必要があります")
# 処理を続行
try:
my_function(-1)
except MyError as e:
print("エラーが発生しました: " + str(e))
実行結果
エラーが発生しました: 値は0以上である必要があります
class MyError(Exception):
独自の例外クラスを定義する場合、Exceptionクラスを継承する必要があります
raise MyError("値は0以上である必要があります")
raise文の後に、独自に定義したクラスを指定します
except MyError as e:
except節でも独自のクラスを指定して例外を捕捉します
【演習問題】
- 次のプログラムを実行すると下のような出力結果が得られます
このプログラムをtry-except文を使い書き換えてみましょう
def add(x, y):
return x + y
mylist = [1,2,3,4,5]
s1 = add(mylist[0],mylist[5])
s2 = add(mylist[0],mylist[4])
print(s1)
print(s2)

- 標準入力から任意の整数を入力し9が入力されたら終了するプログラムをtry-exceptを使用して作成してください
実行結果
任意の整数を入力してください(9:終了):1
1
任意の整数を入力してください(9:終了):d
整数を入力してくださいinvalid literal for int() with base 10: 'd'
任意の整数を入力してください(9:終了):6
6
任意の整数を入力してください(9:終了):9
終了します
コメント