[Pythonのはじめ方] Part17: 例外の種類とカスタム例外


Warning: Undefined array key “is_admin” in /home/c2261046/public_html/omomuki-tech.com/wp-content/themes/sango-theme/library/gutenberg/dist/classes/Toc.php on line 113

Warning: Undefined array key “is_category_top” in /home/c2261046/public_html/omomuki-tech.com/wp-content/themes/sango-theme/library/gutenberg/dist/classes/Toc.php on line 118

Warning: Undefined array key “is_top” in /home/c2261046/public_html/omomuki-tech.com/wp-content/themes/sango-theme/library/gutenberg/dist/classes/Toc.php on line 124

はじめに

前回はtry, except, finallyを使った基本的な例外処理を学びましたね。プログラムを書いていると、予期せぬエラー(例外)が発生することがあります。今回は、Pythonに用意されている様々な組み込み例外の種類と、自分で独自の例外を定義するカスタム例外について学びましょう!💪

例外の種類を理解することで、エラーの原因を特定しやすくなり、より的確なエラーハンドリングが可能になります。

Pythonの組み込み例外 🧱

Pythonには、様々な種類のエラーに対応する多くの組み込み例外クラスが用意されています。すべてを覚える必要はありませんが、よく遭遇する代表的なものを知っておくとデバッグが格段にしやすくなります。

代表的な組み込み例外

以下によく使われる組み込み例外の例をいくつか紹介します。

例外クラス 説明 発生する例
SyntaxError Pythonの文法が間違っている場合に発生します。プログラム実行前に検出されます。
print("Hello" # ← カッコ閉じ忘れ
NameError 定義されていない変数や関数を使用しようとした場合に発生します。
print(my_variable) # ← 定義されていない変数
TypeError 異なるデータ型のオブジェクト間で不適切な操作を行おうとした場合に発生します。
'Hello' + 123 # ← 文字列と数値の結合
ValueError データ型は正しいものの、値が不適切な場合に発生します。
int('abc') # ← 文字列を数値に変換できない
IndexError リストやタプルなどで、存在しないインデックス番号を指定した場合に発生します。
my_list = [1, 2, 3]
print(my_list[3]) # ← 存在しないインデックス
KeyError 辞書で、存在しないキーを指定した場合に発生します。
my_dict = {'a': 1, 'b': 2}
print(my_dict['c']) # ← 存在しないキー
ZeroDivisionError 数値をゼロで割ろうとした場合に発生します。
10 / 0 # ← ゼロ除算
FileNotFoundError 存在しないファイルを開こうとした場合に発生します。
with open('non_existent_file.txt', 'r') as f:
    content = f.read()
ImportError / ModuleNotFoundError 存在しないモジュールをインポートしようとした場合に発生します。(ModuleNotFoundErrorImportError のサブクラスです)
import my_non_existent_module

これら以外にも多くの組み込み例外があります。完全なリストはPythonの公式ドキュメントで確認できます。

💡 ヒント: except節では、特定の例外クラスを指定することで、その種類のエラーだけを捕捉できます。複数の例外をまとめて捕捉したり、より広い範囲の例外(例えばException)を捕捉することも可能です。

例外の階層構造 🌳

Pythonの例外はクラスとして定義されており、他のクラスと同様に継承関係を持っています。全ての組み込み例外はBaseExceptionクラスを頂点とする階層構造になっています。

私たちが通常扱う例外(SystemExitKeyboardInterruptなどを除く)のほとんどは、Exceptionクラスを継承しています。この階層構造を理解しておくと、except節でどのレベルの例外を捕捉するかを考える際に役立ちます。

例えば、ZeroDivisionErrorArithmeticErrorのサブクラス(子クラス)であり、ArithmeticErrorExceptionのサブクラスです。したがって、except ArithmeticError:と書くと、ZeroDivisionErrorだけでなく、OverflowErrorFloatingPointErrorといった他の算術エラーも捕捉できます。

try:
    result = 10 / 0
except ArithmeticError as e:
    print(f"算術エラーが発生しました: {e}") # ZeroDivisionErrorもここで捕捉される
🤔 注意: except Exception:のように、あまりにも広い範囲の例外を捕捉すると、予期しないエラーまで捕捉してしまい、問題の原因特定が難しくなることがあります。可能な限り、具体的な例外クラスを指定するように心がけましょう。

カスタム例外の作成 🛠️

組み込み例外だけでは表現しきれない、アプリケーション固有のエラー状況を扱いたい場合があります。そんなときは、自分でカスタム例外を定義することができます。

カスタム例外を作成するには、Exceptionクラス(またはそのサブクラス)を継承した新しいクラスを定義します。

カスタム例外の定義例

例えば、アプリケーションで「残高不足」という独自のエラーを定義したい場合、次のように書けます。

# 独自例外クラスを定義 (Exceptionを継承)
class InsufficientBalanceError(Exception):
    """残高不足を表すカスタム例外"""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        # 親クラス(Exception)のコンストラクタを呼び出し、エラーメッセージを設定
        super().__init__(f"残高不足です。残高: {balance}, 引き出し額: {amount}")

# 例: このカスタム例外を使用する関数
def withdraw(balance, amount):
    if amount > balance:
        # 残高不足の場合、カスタム例外を発生させる
        raise InsufficientBalanceError(balance, amount)
    else:
        print(f"{amount}円引き出しました。新しい残高: {balance - amount}")
        return balance - amount

# カスタム例外を捕捉する例
my_balance = 1000
try:
    withdraw(my_balance, 1500)
except InsufficientBalanceError as e:
    print(f"エラーが発生しました: {e}")
    # e.balance や e.amount のように、カスタム例外に追加した属性にアクセスできる
    print(f"現在の残高: {e.balance}")
except Exception as e:
    print(f"予期せぬエラーが発生しました: {e}")

カスタム例外を使うメリット ✅

  • コードの可読性向上: エラーの種類が明確になり、何が問題なのか理解しやすくなります。
  • より詳細なエラーハンドリング: アプリケーション固有の状況に応じた、きめ細やかなエラー処理が可能になります。
  • エラー情報の追加: 例外クラスに独自の属性(上の例ではbalanceamount)を持たせることで、エラー発生時の状況に関する追加情報を渡すことができます。

大規模なプログラムやライブラリを開発する際には、カスタム例外を適切に定義することが、コードの保守性や堅牢性を高める上で非常に重要になります。

まとめ 🚀

今回は、Pythonの様々な組み込み例外の種類と、独自のカスタム例外を作成する方法について学びました。

  • 組み込み例外: TypeError, ValueError, IndexErrorなど、よく発生するエラーの種類を理解することが重要です。
  • 例外の階層: 例外クラスは継承関係を持っており、except節で捕捉する範囲を意識することが大切です。
  • カスタム例外: Exceptionクラスを継承して独自の例外を定義することで、アプリケーション固有のエラーを分かりやすく扱えます。

例外処理は、エラーに強いプログラムを作成するための基本です。様々な例外の種類を知り、適切にハンドリングできるようになりましょう! 次回は、プログラムのバグを見つけて修正するための「デバッグ」について学んでいきます。お楽しみに!✨

参考情報 🔗