0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人的アドカレAdvent Calendar 2024

Day 2

Pythonのサブクラスを活用したエラーハンドリングの実装

Posted at

はじめに

Pythonのエラーハンドリングで try ~ except Exception as e のような処理も書けますが、サブクラスを使用する事でより細かなエラーハンドリングをすることができます。本記事ではこれらを使用したエラーハンドリングについて簡単な例を実装していきます。

サブクラスを使用するメリット

  • エラーの種類ごとに異なる処理が可能
  • 各エラーに対してエラーメッセージをより具体的に設定できる
  • エラーの階層構造を作れる

具体例

デフォルトの Exception と サブクラス を使用したものを1つずつ見てみます。

例1:Exception クラス

def connect_database():
    try:
        # データベース接続の処理
        connection = db.connect()
    except Exception as e:
        # すべてのエラーを一括で処理
        print(f"エラーが発生しました: {e}")
        return None

上記の場合、エラーメッセージ(= e )から何が原因なのかを読み取ることはできますが、エラーの種類ごとに異なる処理を書くことができません。
例えば「接続エラーの場合は再接続を試みる」「タイムアウトの場合は少し待ってから再接続する」といった処理の振り分けができません。

例2:サブクラス

def connect_database():
    try:
        # データベース接続の処理
        connection = db.connect()
        
    except ConnectionError as e:
        # 接続エラーの場合の処理
        print(f"接続エラー: {e}")
        # 再接続を試みる
        return retry_connection()
        
    except TimeoutError as e:
        # タイムアウトの場合の処理
        print(f"タイムアウト: {e}")
        # 時間をおいて再接続
        return wait_and_retry()
        
    except Exception as e:
        # 想定外のエラーの処理
        print(f"予期せぬエラーが発生しました: {e}")
        return None

サブクラスを使用するとエラーの種類によって異なる対処が可能です。
例えば、接続エラーの場合はすぐに再接続を試み、タイムアウトの場合は少し時間をおいてから再試行するなど、状況に応じた適切な処理を実装できます。

サブクラスを使用した処理の実行例

例としてファイル読み込みの処理をクラスとして定義し、サブクラスを使用した処理を実行していきます。

index.py
def read_file(filepath):
    # ファイルの読み込みを行う関数
    with open(filepath, 'r') as f:
        return f.read()

def try_read(filepath):
    try:
        # ファイルを読み込む
        content = read_file(filepath)
        print(f"ファイルの内容: {content}")
        
    except FileNotFoundError as e:
        # ファイルが存在しない場合の処理
        print(f"ファイルが見つかりません: {e}")
        
    except TypeError as e:
        # ファイルパスの型が不正な場合の処理
        print(f"ファイルパスの型が不正です: {e}")
        
    except Exception as e:
        # その他の予期せぬエラーの処理
        print(f"予期せぬエラー: {e}")

# test.txtファイルは事前に作成されてる想定
print("1. 正常な実行:")
try_read("test.txt")

print("\n2. 存在しないファイルの読み込み:")
try_read("not_exist.txt")

print("\n3. 不正な型のファイルパス:")
try_read(None)

read_file, try_read について

  1. read_file関数について

    • read_fileメソッド:与えられたファイルパスのファイルを読み込む
      • ファイルが存在する場合:内容を返す
      • ファイルが存在しない場合:FileNotFoundErrorを発生
      • パスの型が不正な場合:TypeErrorを発生
  2. try_read関数について

    • read_file関数のインスタンスを作成
    • ファイル読み込みを試みて、発生するエラーの種類に応じて処理を分岐
    • エラーメッセージを出力

スクリプトを実行

次のコマンドで処理を実行してみます。

python .\index.py

スクリプトを実行する前に、カレントディレクトリに test.txt が準備されている事を想定しています。
本記事では Hello, World! と書き込んだものを使用しています。

1. 正常な実行:
ファイルの内容: Hello, World!

2. 存在しないファイルの読み込み:
ファイルが見つかりません: [Errno 2] No such file or directory: 'not_exist.txt'

3. 不正な型のファイルパス:
ファイルパスの型が不正です: expected str, bytes or os.PathLike object, not NoneType

各ケースの動作を詳しく見てみましょう:

  1. 正常系(test.txt)

    • 実在するファイルなので読み込み成功
    • ファイルの内容(Hello, World!)が表示される
  2. 存在しないファイル(not_exist.txt)

    • ファイルが存在しないのでFileNotFoundErrorが発生
    • エラーをキャッチして適切なメッセージ(ファイルが見つかりません)を表示
  3. 不正な型のパス(None)

    • 文字列以外のパスなのでTypeErrorが発生
    • エラーをキャッチして適切なメッセージ(ファイルパスの型が不正です)を表示

このように、エラーの種類に応じて異なるメッセージを表示し、適切な処理を行うことができます。

参考

https://docs.python.org/ja/3/library/exceptions.html#FileNotFoundError
https://docs.python.org/ja/3/library/exceptions.html#TypeError
https://docs.python.org/ja/3/library/exceptions.html#Exception

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?