Python入門【例外処理・独自の例外の定義】

Python Exception

こんにちは、ミナトです。

「エラーが発生した際、適切にエラーハンドリングを行い処理を継続したい」と言うケースがあるかと思います。そのような場合は例外処理を定義する必要があります。

今回はPythonで例外処理を行う方法について解説します。

エラーを適切に処理するには例外処理を行う必要があるで!

今回はPythonの例外処理について解説するな😆

以下のような方を対象としています
  • Pythonの例外処理について知りたい
  • 独自の例外を定義したい
  • Pythonでプログラミングを学びたい

例外処理

例外とは?

例外(Exception)とは、プログラムの実行中に発生したエラーを伝える仕組みのことです。

Pythonの例外はクラスとして定義されており、プログラムの実行中にエラーが起こると例外オブジェクトが生成されます。

Pythonには数多くの例外クラスが定義されており、エラーの内容によって生成されるクラスが異なります。興味のある方は以下のドキュメントをご確認ください。

組み込み例外

Pythonの例外クラスは基本的にExceptionクラスを継承したクラスで、独自の例外クラスを定義することも可能です。

例外処理とは?

プログラムの実行中にエラーが発生するとそこで処理が終わってしまいます。処理の内容によっては、例外が発生してもそのまま処理を継続したい場合があります。そのような場合に例外処理を利用します。

例外処理は、エラーが発生した際に何か終了処理を行ったり、そのまま処理を継続できるようにエラーハンドリングする仕組みだと言えます。

例えば、例外が発生した場合にデータベースとの接続を切ったり、開いているファイルを閉じたり、ログを出力するなどの終了処理を行うケースが考えられます。

例外処理の定義

例外処理の記述方法をまとめると以下のようになります。

例外処理の定義 まとめ
項目説明
try例外が発生する可能性のある処理を記述します。
except全ての例外をキャッチしたい場合、例外発生時の処理を記述します。
except 例外クラス名特定の例外クラスをキャッチしたい場合、例外発生時の処理を記述します。
except 例外クラス名 as 変数名特定の例外クラスをキャッチしたい場合、例外発生時の処理を記述します。さらに、例外オブジェクトを変数に受け取り詳細な情報を取得できます。
else例外が発生しなかった場合の処理を記述します。
finally例外が発生した場合、しなかった場合ともに必ず実行する処理を定義します。

全ての例外をキャッチする

例外処理の定義にはtry except 文を利用します。

例外処理の定義①

try:
 処理
except:
 例外発生時の処理

以下の例では、3つの要素をもつリストlから存在しないインデックスの要素を取得しようとしています。
しかし、「IndexError」が発生して、後続の処理print('処理2')が実行されません。

l = [1, 2, 3]
i = 3

print(l[i])
print('処理2')


## 出力
Traceback (most recent call last):
  File "/Users/minato/PycharmProjects/pythonProject/lesson1.py", line 4, in <module>
    print(l[i])
IndexError: list index out of range

以下のように例外処理を定義することで、エラーハンドリングを行い、処理を継続できます。

try文の中で例外が発生するとexcept文が実行され、そのまま処理は継続されます。
以下の場合、全ての例外クラスをキャッチします。

l1 = [1, 2, 3]
i = 3

try:
    print(l1[i])
except:
    print('例外発生')

print('処理2')


## 出力
例外発生
処理2

特定の例外クラスのみキャッチする

通常全ての例外クラスをキャッチするのではなく、想定される例外を絞ってキャッチする方が良いとされています。
特定の例外クラスに絞ってキャッチする場合は以下のように記述します。

例外処理の定義②

try:
 処理
except 例外クラス名:
 例外発生時の処理

以下の例では、IndexErrorクラスをキャッチします。他のクラスの例外はキャッチしなくなるので注意してください。

l1 = [1, 2, 3]
i = 3

try:
    print(l1[i])
except IndexError:
    print('例外発生')

print('処理2')


## 出力
例外発生
処理2

また、キャッチする例外クラスは複数定義することも可能です。

以下の例では、二つ目で「NameError」をキャッチしています。

l1 = [1, 2, 3]
i = 3

try:
    print(l[i])
except IndexError:
    print('例外発生1')
except NameError:
    print('例外発生2')

print('処理2')


## 出力
例外発生2
処理2

基本的には受け取る例外クラスを指定して記述するのが望ましいですが、どのような例外が発生するか分からない場合など、ざっくり例外をキャッチしたい場合は以下のように記述できます。

l1 = [1, 2, 3]
i = 3

try:
    print(l[i])
except IndexError:
    print('例外発生1')
except:
    print('その他の例外')

print('処理2')


## 出力
その他の例外
処理2

また、ほとんどの組み込みの例外クラスがExceptionクラスを継承しているので以下の様にも記述できます。
クラスの継承については別の機会に解説したいと思います。

l1 = [1, 2, 3]
i = 3

try:
    print(l[i])
except IndexError:
    print('例外発生1')
except Exception:
    print('その他の例外')

print('処理2')


## 出力
その他の例外
処理2

except文の中で発生した例外オブジェクトを利用する

以下のように変数を定義することで、except文の中でより詳細な例外の情報を取得することができます。

例外処理の定義③

try:
 処理
except 例外クラス名 as 変数名:
 例外発生時の処理

l1 = [1, 2, 3]
i = 3

try:
    print(l1[i])
except IndexError as ex:
    print(f'例外発生 {ex}')


print('処理2')


## 出力
例外発生 list index out of range
処理2

例外が発生しなかった場合の処理

try else 文を利用すると例外が発生しなかった時の処理を定義できます。

例外処理の定義④

try:
 処理
except 例外クラス名 as 変数名:
 例外発生時の処理
else:
 例外が発生しない場合の処理

以下の例では、try文の中の処理で例外が発生しないため、else文の中の処理が実行されます。

l1 = [1, 2, 3]
i = 0

try:
    print(l1[i])
except IndexError as ex:
    print(f'例外発生 {ex}')
else:
    print('例外が発生しませんでした。')


print('処理2')


## 出力
1
例外が発生しませんでした。
処理2

最後に必ず実行する処理

try finally 文を利用することで、例外が発生しても、しなくても必ず実行される処理を定義できます。

例外処理の定義⑤

try:
 処理
except 例外クラス名 as 変数名:
 例外発生時の処理
else:
 例外が発生しない場合の処理
finally
 必ず実行される処理

以下の例では、例外が発生しないため、else文とfinally文の両方が実行されます。

l1 = [1, 2, 3]
i = 0

try:
    print(l1[i])
except IndexError as ex:
    print(f'例外発生 {ex}')
else:
    print('例外が発生しませんでした。')
finally:
    print('必ず実行される処理')


print('処理2')


## 出力
1
例外が発生しませんでした。
必ず実行される処理
処理2

続いて、i = 3に変更して「IndexError」を発生させます。今度はexcept文とfinally文が実行されることが確認できます。

l1 = [1, 2, 3]
i = 3

try:
    print(l1[i])
except IndexError as ex:
    print(f'例外発生 {ex}')
else:
    print('例外が発生しませんでした。')
finally:
    print('必ず実行される処理')


print('処理2')


## 出力
例外発生 list index out of range
必ず実行される処理
処理2

独自の例外の定義

ここまでの例外処理の解説でPythonには多くの組み込み例外クラスがあることをご紹介しました。

組み込み例外

Pythonでは、上記の組み込み例外クラスに加えて、自分独自の例外クラスを定義できます。

例外を発生させる

独自例外の定義の前に例外を発生させる方法を紹介します。
プログラムの中でraiseを利用すると例外を発生させることができます。

raise IndexError('IndexErrorを発生を発生させました。')

独自の例外を定義する

独自例外を定義するには、例外のベースとなるクラスExceptionクラスを継承したクラスを定義します。クラスの継承については別の機会に解説します。

独自の例外クラスの定義

class クラス名(Exception):
 pass

以下の例では、MyErrorとう例外クラスを定義しています。

check_number()関数の引数が10より大きい時にMyErrorをraiseしています。

このように自分独自の例外を定義しておくことで、エラーの内容が明確となり、どのような対応をしたらいいかプロジェクトの中で管理しやすくなります。

class MyError(Exception):
    pass


def check_number(num):
    if num > 10:
        raise MyError(f'{num}は10より大きいです。')


try:
    check_number(11)
except MyError as ex:
    print('独自の例外が発生しました。')
    print(ex)


## 出力
独自の例外が発生しました。
11は10より大きいです。

まとめ

今回はPythonにをおける例外処理について解説しました。
例外処理の特徴は以下の通りです。

例外処理の特徴
  • 例外処理とは、エラーを適切に扱いプログラムの処理を継続する仕組みのこと
  • try except 文を利用することで例外処理を定義できる
  • Exceptionクラスを継承することで、独自の例外を定義できる

例外処理を定義することで、プログラムの実行時に発生する思わぬエラーを適切に扱うことができます。
例外処理の使い方はしっかり覚えておきましょう。

最後まで読んでいただき、ありがとうございます。

この記事が「面白いな」、「勉強になったな」という方は、SNSでシェアしていただけると嬉しいです。