プログラムを作成していると、ユーザーの入力ミスやファイルの読み込み失敗など、さまざまな原因でエラーが発生することがあります。エラーが発生すると、プログラムは通常そのまま終了してしまいますが、適切にエラーに対処することで、プログラムの安定性を保つことができます。
この章では、Pythonにおける例外処理について学びます。エラーが発生してもプログラムを正常に動作させるための**try-except
** 構文の使い方や、独自のカスタム例外を作成する方法について解説します。
8.1 エラーと例外
Pythonでエラーが発生すると、プログラムは通常「例外(exception)」という形でエラーを報告します。例外は、予期しない事態やプログラムの動作を妨げる問題を指し、これが処理されないとプログラムがクラッシュしてしまいます。
例えば、次のコードを見てみましょう。
print(10 / 0)
このコードを実行すると、ZeroDivisionError というエラーが発生します。これは「0で割る」という数学的に無効な操作が原因です。
ZeroDivisionError: division by zero
このようなエラーが発生した場合でも、適切に処理することでプログラムをクラッシュさせずに済ませることができます。
8.2 try-except
文の基本
Pythonでは、エラーが発生する可能性があるコードを**try
** ブロックに書き、そのエラーを**except
** ブロックでキャッチして処理する方法が提供されています。この構文を使うことで、プログラムがエラーで停止せずに、代わりにエラーメッセージを表示したり、別の処理に移行することができます。
8.2.1 基本的な try-except
構文
try-except
文の基本構造は以下の通りです:
try:
# エラーが発生するかもしれないコード
except:
# エラーが発生したときの処理
実際の例を見てみましょう。
try:
print(10 / 0)
except:
print("エラーが発生しました。0で割ることはできません。")
このコードでは、0で割る操作を試みていますが、except
ブロックがエラーをキャッチし、エラーメッセージが表示されます。これにより、プログラムがクラッシュせずに続行されます。
エラーが発生しました。0で割ることはできません。
8.3 具体的な例外のキャッチ
except
ブロックでエラーをキャッチする際、すべてのエラーを一律に処理するだけでなく、特定の種類の例外を指定して、それに応じた処理を行うことも可能です。
8.3.1 特定の例外を指定する
次に、特定の例外だけをキャッチして処理する方法を見てみましょう。たとえば、0で割った場合にはZeroDivisionError だけをキャッチして、そのエラーに特化したメッセージを表示します。
try:
print(10 / 0)
except ZeroDivisionError:
print("ゼロでの除算エラーが発生しました。")
実行結果は次の通りです。
ゼロでの除算エラーが発生しました。
ZeroDivisionError
以外のエラーが発生した場合は、これではキャッチされず、そのままエラーメッセージが表示されます。
8.3.2 複数の例外を処理する
複数の異なるエラーに対処するために、except
ブロックを複数設けることもできます。例えば、ZeroDivisionError
と ValueError
を別々に処理する場合は次のように書きます。
try:
num = int(input("数字を入力してください: "))
print(10 / num)
except ZeroDivisionError:
print("ゼロで割ることはできません。")
except ValueError:
print("無効な入力です。整数を入力してください。")
このコードでは、ユーザーが 0
を入力した場合には ZeroDivisionError
が発生し、無効な文字列を入力した場合には ValueError
が発生します。それぞれのエラーに対して異なるメッセージを表示することができます。
8.4 例外オブジェクトの利用
except
ブロックでは、発生した例外の詳細な情報を取得するために、例外オブジェクトを使うことができます。例外オブジェクトを使うことで、エラーメッセージやエラーの種類に基づいて柔軟に処理を行うことが可能です。
8.4.1 例外オブジェクトを取得する
次の例では、as
キーワードを使って例外オブジェクトを取得し、その内容を表示します。
try:
print(10 / 0)
except ZeroDivisionError as e:
print(f"エラーが発生しました: {e}")
このコードでは、e
に例外オブジェクトが格納され、エラーメッセージが次のように表示されます。
エラーが発生しました: division by zero
例外オブジェクトを使うことで、エラーの内容をログに保存したり、より詳細なエラーメッセージを表示することができます。
8.5 else
とfinally
の利用
try-except
構文では、例外が発生しなかった場合に処理を行うための else
ブロックや、例外の発生有無に関係なく必ず実行したい処理を記述する finally
ブロックも利用できます。
8.5.1 else
ブロック
else
ブロックは、try
内でエラーが発生しなかった場合にのみ実行されます。
try:
num = int(input("数字を入力してください: "))
result = 10 / num
except ZeroDivisionError:
print("ゼロで割ることはできません。")
except ValueError:
print("無効な入力です。整数を入力してください。")
else:
print(f"結果は: {result}")
このコードでは、エラーが発生しなかった場合に else
ブロックの中の処理が実行され、結果が表示されます。
8.5.2 finally
ブロック
finally
ブロックは、例外が発生したかどうかにかかわらず、必ず最後に実行されます。これを使って、リソースの解放やファイルのクローズ処理など、後始末を確実に行いたい場合に使用します。
try:
file = open('example.txt', 'r')
content = file.read()
except FileNotFoundError:
print("ファイルが見つかりませんでした。")
finally:
file.close()
print("ファイルを閉じました。")
この例では、ファイルの読み込みに失敗した場合でも、finally
ブロックで確実にファイルを閉じる処理が行われます。
8.6 カスタム例外の作成
Pythonでは、標準で用意されている例外だけでなく、カスタム例外を作成して、独自のエラーハンドリングを行うこともできます。カスタム例外を作成することで、特定のエラーメッセージやエラー状態を管理しやすくなります。
8.6.1 カスタム例外クラスの作成
カスタム例外を作成するには、Pythonの組み込み例外クラス Exception
を継承して新しいクラスを定義します。
class CustomError(Exception):
pass
# カスタム例外を発生させる
def divide(a, b):
if b == 0:
raise CustomError("0で割ることはできません。")
return a / b
try:
result = divide(10, 0)
except CustomError as e:
print(f"カスタムエラーが発生しました: {e}")
このコードでは、b
が 0
の場合に CustomError
というカスタム例外を発生させ、そのエラーをキャッチしてメッセージを表示しています。
カスタムエラーが発生しました: 0で割ることはできません。
8.7 よく使われる組み込み例外
Pythonには、さまざまな組み込みの例外クラスが用意されています。ここでは、よく使われる例外のいくつかを紹介します。
ZeroDivisionError
:ゼロで割ろうとしたときに発生します。ValueError
:無効な値が使われたときに発生します(例:文字列を整数に変換しようとしたとき)。FileNotFoundError
:指定したファイルが存在しない場合に発生します。TypeError
:不適切な型のデータに対して操作を行おうとしたときに発生します。
これらの例外を知っておくことで、発生するエラーに対して適切に対処できるようになります。
まとめ
この章では、Pythonの例外処理について学びました。try-except
を使ってエラーをキャッチし、プログラムが中断せずに処理を続行できるようにする方法や、特定の例外をキャッチして適切に処理する方法を学びました。また、カスタム例外を作成して独自のエラーハンドリングを行う方法も紹介しました。例外処理を理解し、正しく使うことで、プログラムの信頼性と安定性を大幅に向上させることができます。