<一覧に戻る

例外処理の工夫

Pythonでは、プログラムの実行中に発生するエラーや例外を適切に処理することが重要です。例外処理を適切に行うことで、プログラムの安定性を向上させ、ユーザーにとっても使いやすいソフトウェアを提供できます。この教材では、実践的な例外処理のテクニックをいくつか紹介します。

1. 基本的な例外処理

まずは基本的な例外処理の構文を見てみましょう。以下のサンプルコードでは、ユーザーから整数の入力を受け取り、その整数を2で割るプログラムを示します。

def divide_by_two():
    try:
        user_input = int(input("整数を入力してください: "))
        result = user_input / 2
        print(f"{user_input}を2で割った結果: {result}")
    except ValueError:
        print("無効な入力です。整数を入力してください。")
    except ZeroDivisionError:
        print("ゼロで割ることはできません。")
    except Exception as e:
        print(f"予期しないエラーが発生しました: {e}")

divide_by_two()

解説

  • tryブロック内では、ユーザー入力を整数に変換し、その値を2で割る処理を行います。
  • exceptブロックでは、ValueErrorZeroDivisionErrorの2つの例外を個別に処理しています。
  • 最後のexcept Exception as e:では、他のすべての例外をキャッチし、エラーメッセージを表示します。このようにすることで、予期しないエラーも適切に処理できます。

2. 例外のログ出力

例外が発生した場合、エラーログを記録することも重要です。以下のコードでは、例外が発生した場合にエラーメッセージをファイルに書き込む方法を示します。

import logging

# ログ設定
logging.basicConfig(filename='error.log', level=logging.ERROR)

def divide_by_two_with_logging():
    try:
        user_input = int(input("整数を入力してください: "))
        result = user_input / 2
        print(f"{user_input}を2で割った結果: {result}")
    except ValueError as ve:
        logging.error(f"無効な入力: {ve}")
        print("無効な入力です。整数を入力してください。")
    except ZeroDivisionError as zde:
        logging.error(f"ゼロで割る試行: {zde}")
        print("ゼロで割ることはできません。")
    except Exception as e:
        logging.error(f"予期しないエラー: {e}")
        print(f"予期しないエラーが発生しました: {e}")

divide_by_two_with_logging()

解説

  • loggingモジュールを使用して、エラーログをファイルに書き込みます。
  • exceptブロックでは、例外情報をログに記録するために、logging.error()を呼び出しています。これにより、後で問題の診断がしやすくなります。

3. 例外を再発生させる

時には、例外を捕捉した後に、再度発生させる必要がある場合があります。以下の例では、エラーが発生した場合にそのエラーを再スローしています。

def divide_by_two_with_rethrow():
    try:
        user_input = int(input("整数を入力してください: "))
        result = user_input / 2
        print(f"{user_input}を2で割った結果: {result}")
    except ValueError as ve:
        print("無効な入力です。整数を入力してください。")
        raise  # 例外を再スロー
    except ZeroDivisionError as zde:
        print("ゼロで割ることはできません。")
        raise  # 例外を再スロー
    except Exception as e:
        print(f"予期しないエラーが発生しました: {e}")
        raise  # 例外を再スロー

try:
    divide_by_two_with_rethrow()
except Exception as e:
    print(f"例外が再発生しました: {e}")

解説

  • raise文を使って、捕捉した例外を再スローしています。これにより、呼び出し元でのさらなるエラーハンドリングが可能になります。
  • 最後のtryブロックでは、再発生した例外を捕捉し、適切なメッセージを表示します。

4. カスタム例外の定義

独自の例外を定義することで、プログラムのエラーハンドリングをより柔軟にすることができます。以下のコードでは、カスタム例外を定義し、それを使用しています。

class CustomError(Exception):
    pass

def divide_by_two_with_custom_exception():
    try:
        user_input = int(input("整数を入力してください: "))
        if user_input < 0:
            raise CustomError("負の数は許可されていません。")
        result = user_input / 2
        print(f"{user_input}を2で割った結果: {result}")
    except ValueError:
        print("無効な入力です。整数を入力してください。")
    except CustomError as ce:
        print(ce)
    except Exception as e:
        print(f"予期しないエラーが発生しました: {e}")

divide_by_two_with_custom_exception()

解説

  • CustomErrorというカスタム例外を定義しています。
  • ユーザーが負の数を入力した場合、このカスタム例外を発生させています。
  • except CustomError as ce:ブロックで、このカスタム例外を処理します。

まとめ

例外処理は、プログラムの安定性を高め、ユーザーにとって使いやすいソフトウェアを提供するために不可欠です。この教材では、基本的な例外処理からカスタム例外の定義まで、さまざまなテクニックを紹介しました。実際のプロジェクトでこれらのテクニックを活用し、より堅牢なプログラムを作成してください。

出力結果: