Python で関数が例外を発生させるかどうかを確認する方法

PythonPythonBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Python で関数が例外を発生させるかどうかを確認する方法を学びます。実験ではまず、例外と、関数内で例外が発生する仕組みを調べます。ZeroDivisionError を発生させる可能性のある単純な Python 関数を作成し、例外が発生したときのトレースバックを確認します。

次に、try-except ブロックを実装して、例外を適切に処理します。最後に、pytest.raises を使用して、関数が特定の例外を発生させるかどうかをテストする方法を学びます(オプションの紹介)。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") subgraph Lab Skills python/catching_exceptions -.-> lab-559520{{"Python で関数が例外を発生させるかどうかを確認する方法"}} python/raising_exceptions -.-> lab-559520{{"Python で関数が例外を発生させるかどうかを確認する方法"}} end

関数内の例外を調べる

このステップでは、Python の関数内で例外がどのように発生するかについて学びます。例外を理解することは、堅牢で信頼性の高いコードを書くために重要です。例外とは、プログラムの通常の実行フローを中断するイベントです。例外は、無効な入力、ファイルが見つからない、ネットワークエラーなど、様々な理由で発生する可能性があります。

まず、例外を発生させる可能性のある単純な Python 関数を作成しましょう。LabEx 環境の VS Code エディタを開き、~/project ディレクトリに exceptions_example.py という名前の新しいファイルを作成します。

## ~/project/exceptions_example.py
def divide(x, y):
    return x / y

print(divide(10, 2))
print(divide(5, 0))

このコードでは、以下のことを行っています。

  • xy の 2 つの引数を取り、xy で割った結果を返す divide という関数を定義しています。
  • 最初に、引数 102divide 関数を呼び出しており、これによりコンソールに 5.0 が出力されます。
  • 次に、引数 50divide 関数を呼び出しています。これにより、ゼロでの除算は許されていないため、ZeroDivisionError が発生します。

では、このスクリプトを実行しましょう。VS Code のターミナルを開き(「表示」 -> 「ターミナル」から見つけることができます)、以下のコマンドを実行します。

python ~/project/exceptions_example.py

以下のような出力が表示されます。

5.0
Traceback (most recent call last):
  File "/home/labex/project/exceptions_example.py", line 4, in <module>
    print(divide(5, 0))
  File "/home/labex/project/exceptions_example.py", line 2, in divide
    return x / y
ZeroDivisionError: division by zero

ご覧の通り、最初の print 文は正常に実行され、結果 5.0 が出力されました。しかし、y = 0divide 関数が呼び出されたときに ZeroDivisionError が発生し、プログラムは終了しました。トレースバックは、例外に至るまでの関数呼び出しのシーケンスを示しており、デバッグに役立ちます。

この例は、関数内で例外が発生する可能性があり、それがプログラムの通常の実行フローを中断することを示しています。次のステップでは、tryexcept ブロックを使用して例外を処理する方法を学びます。

try-except ブロックを実装する

前のステップでは、例外がプログラムを突然終了させる可能性があることを見ました。例外を適切に処理し、プログラムのクラッシュを防ぐために、tryexcept ブロックを使用することができます。

try ブロックを使用すると、例外を発生させる可能性のあるコードのセクションを囲むことができます。try ブロック内で例外が発生した場合、プログラムは対応する except ブロックにジャンプし、そこで例外を処理することができます。

exceptions_example.py ファイルを変更して、ZeroDivisionError を処理する try-except ブロックを追加しましょう。VS Code エディタで exceptions_example.py ファイルを開き、以下のように変更します。

## ~/project/exceptions_example.py
def divide(x, y):
    try:
        result = x / y
        return result
    except ZeroDivisionError:
        return "Cannot divide by zero!"

print(divide(10, 2))
print(divide(5, 0))
print(divide(8, 4))

この変更後のコードでは、以下のことを行っています。

  • x / y の演算を try ブロックで囲んでいます。これは、除算中に ZeroDivisionError が発生した場合、プログラムが except ブロックにジャンプすることを意味します。
  • except ZeroDivisionError: の行は、ZeroDivisionError 例外を処理したいことを指定しています。
  • except ブロック内では、文字列 "Cannot divide by zero!" を返しています。これにより、プログラムがクラッシュする代わりに、このメッセージがコンソールに出力されます。

では、変更後のスクリプトを実行しましょう。VS Code のターミナルを開き、以下のコマンドを実行します。

python ~/project/exceptions_example.py

以下のような出力が表示されます。

5.0
Cannot divide by zero!
2.0

ご覧の通り、ゼロで除算するときにプログラムはもはやクラッシュしません。代わりに、except ブロックが ZeroDivisionError を捕捉し、メッセージ "Cannot divide by zero!" が出力されます。その後、プログラムは引き続き実行され、最後の print 文も正常に実行されます。

try-except ブロックは、他のタイプの例外を処理するためにも使用できます。たとえば、互換性のないデータ型に対して演算を行おうとした場合に発生する TypeError 例外を処理するために try-except ブロックを使用することができます。また、複数の except ブロックを使用して、異なるタイプの例外を処理することもできます。

次のステップでは、pytest を使用して例外をテストする方法について学びます。

pytest.raises を使ったテスト (オプションの紹介)

このオプションのステップでは、pytest を使って例外をテストする方法を簡単に紹介します。pytest は Python の人気のあるテストフレームワークで、テストの作成と実行のプロセスを簡素化します。

まず、pytest をインストールしましょう。VS Code のターミナルを開き、以下のコマンドを実行します。

pip install pytest

このコマンドにより、pytest とその依存関係がダウンロードされ、インストールされます。

次に、divide 関数のテストファイルを作成しましょう。~/project ディレクトリに test_exceptions.py という名前の新しいファイルを作成します。

## ~/project/test_exceptions.py
import pytest
from exceptions_example import divide

def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        divide(5, 0)

def test_divide_valid():
    assert divide(10, 2) == 5

このコードでは、以下のことを行っています。

  • pytest モジュールと exceptions_example.py ファイルから divide 関数をインポートしています。
  • test_divide_by_zero というテスト関数を定義しています。この関数は pytest.raises を使って、divide(5, 0) を呼び出すと ZeroDivisionError が発生することをアサートします。with pytest.raises(ZeroDivisionError): ブロックは、ブロック内で ZeroDivisionError が発生した場合にのみテストが合格することを保証します。
  • test_divide_valid という別のテスト関数を定義しています。この関数は、divide(10, 2) を呼び出すと値 5 が返されることをアサートします。

テストを実行するには、VS Code のターミナルを開き、以下のコマンドを実行します。

pytest ~/project/test_exceptions.py

以下のような出力が表示されるはずです。

============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-7.4.4, pluggy-1.3.0
rootdir: /home/labex/project
collected 2 items

test_exceptions.py ..                                                      [100%]

============================== 2 passed in 0.01s ===============================

この出力は、2 つのテストが収集され、両方のテストが合格したことを示しています。これは、divide 関数が期待通りに動作していることを示しています。つまり、ゼロで除算すると ZeroDivisionError が発生し、ゼロ以外の数で除算すると正しい結果が返されます。

これは pytest を使って例外をテストする非常に基本的な例です。pytest には、より包括的で効果的なテストを書くのに役立つ多くの他の機能があります。

まとめ

この実験では、Python 関数における例外を探索することから始め、例外がプログラムの通常の流れを中断するイベントであることを理解しました。ゼロで除算すると ZeroDivisionError を発生させる divide 関数を作成しました。スクリプトを実行することで、例外がどのようにプログラムを終了させ、デバッグ用のトレースバックを提供するかを確認しました。

この実験では、堅牢なコードを書くために例外を理解することの重要性を強調しています。例外を発生させることができる関数の簡単な例と、例外が発生したときに結果として得られるエラーとトレースバックを観察する方法を紹介しています。