プログラムの実行中にエラーが発生することは避けられません。例外処理を使えば、エラーが発生してもプログラムがクラッシュせず、適切に対応できます。Pythonではtry-except文を使って例外を捕捉し、処理します。
この記事では、例外処理の基本から、複数の例外の処理、finally、カスタム例外まで詳しく解説します。
基本的な使い方
tryブロックにエラーが起きうるコードを書き、exceptブロックでエラー時の処理を記述します。
Python
# 例外処理なし(エラーでクラッシュ)
# result = 10 / 0 # ZeroDivisionError
# 例外処理あり
try:
result = 10 / 0
except ZeroDivisionError:
print("エラー: 0で割ることはできません")
print("プログラムは続行します")
# 数値変換のエラー処理
try:
number = int("abc")
except ValueError:
print("エラー: 数値に変換できません")
実行結果
エラー: 0で割ることはできません
プログラムは続行します
エラー: 数値に変換できません
複数の例外を処理する
Python
# 複数のexcept節
def safe_divide(a, b):
try:
result = a / b
return result
except ZeroDivisionError:
print("エラー: 0で割ることはできません")
return None
except TypeError:
print("エラー: 数値を入力してください")
return None
print(safe_divide(10, 3))
print(safe_divide(10, 0))
print(safe_divide("10", 3))
# 複数の例外をまとめて処理
try:
data = [1, 2, 3]
print(data[10])
except (IndexError, KeyError) as e:
print(f"エラー: {type(e).__name__} - {e}")
実行結果
3.3333333333333335
エラー: 0で割ることはできません
None
エラー: 数値を入力してください
None
エラー: IndexError - list index out of range
else と finally
elseは例外が発生しなかった場合、finallyは例外の有無にかかわらず必ず実行されます。
Python
def read_number(text):
try:
number = int(text)
except ValueError:
print(f"'{text}' は数値ではありません")
else:
print(f"変換成功: {number}")
finally:
print("処理完了")
print("---")
read_number("42")
read_number("abc")
実行結果
変換成功: 42
処理完了
---
'abc' は数値ではありません
処理完了
---
例外の情報を取得する
Python
# as でエラーオブジェクトを取得
try:
with open("nonexistent.txt", "r") as f:
content = f.read()
except FileNotFoundError as e:
print(f"例外の型: {type(e).__name__}")
print(f"メッセージ: {e}")
# すべての例外をキャッチ(非推奨だが緊急時に使用)
try:
result = 1 / 0
except Exception as e:
print(f"予期しないエラー: {type(e).__name__}: {e}")
実行結果
例外の型: FileNotFoundError
メッセージ: [Errno 2] No such file or directory: 'nonexistent.txt'
予期しないエラー: ZeroDivisionError: division by zero
except Exceptionの使い方に注意
except Exception ですべてのエラーをキャッチするのは、バグを隠してしまう可能性があるため推奨されません。可能な限り、具体的な例外クラスを指定しましょう。
例外を発生させる(raise)
Python
def set_age(age):
if not isinstance(age, int):
raise TypeError("年齢は整数で指定してください")
if age < 0 or age > 150:
raise ValueError(f"年齢の範囲が不正です: {age}")
return age
try:
set_age(25)
print("正常: 25歳")
set_age(-5)
except ValueError as e:
print(f"ValueError: {e}")
try:
set_age("二十歳")
except TypeError as e:
print(f"TypeError: {e}")
実行結果
正常: 25歳
ValueError: 年齢の範囲が不正です: -5
TypeError: 年齢は整数で指定してください
代表的な例外クラス
ValueError: 不正な値、TypeError: 型の不一致、KeyError: 辞書のキーが存在しない、IndexError: インデックス範囲外、FileNotFoundError: ファイルが見つからない、ZeroDivisionError: 0での除算、AttributeError: 存在しない属性へのアクセス。
実践的な使い方
Python
import json
# 設定ファイルの安全な読み込み
def load_config(filepath):
try:
with open(filepath, "r", encoding="utf-8") as f:
config = json.load(f)
return config
except FileNotFoundError:
print(f"設定ファイルが見つかりません: {filepath}")
return {}
except json.JSONDecodeError as e:
print(f"JSONの形式が不正です: {e}")
return {}
config = load_config("config.json")
print(f"設定: {config}")
db_host = config.get("db_host", "localhost")
db_port = config.get("db_port", 5432)
print(f"接続先: {db_host}:{db_port}")
実行結果
設定ファイルが見つかりません: config.json
設定: {}
接続先: localhost:5432
まとめ
try-exceptでエラーを捕捉してプログラムのクラッシュを防ぐ- 具体的な例外クラスを指定して、適切にエラーを処理する
elseは正常時、finallyは常に実行されるraiseで意図的に例外を発生させて不正な値を検出できるexcept Exceptionですべてキャッチするのは避け、具体的な例外を指定する