Pythonにおける例外処理は「try-except」構文を中心に、finally・else・raiseなどのキーワードを組み合わせて実装します。
Pythonは他の言語と比べてシンプルかつ直感的な例外処理の構文を持っており、初心者でも理解しやすい設計になっています。
しかしシンプルさの中にも、Pythonならではの特徴や注意すべきポイントが存在します。
本記事では、例外処理のPythonでの書き方、構文と使い方、try-except・finally・else・raise・カスタム例外・Exception処理などについて詳しく解説していきます。
Python初心者の方はもちろん、より品質の高いPythonコードを書きたいという方にも役立つ内容ですので、ぜひ参考にしてください。
Pythonの例外処理の基本はtry-except構文で例外を捕捉すること
それではまず、Pythonにおける例外処理の基本構文と動作の仕組みについて解説していきます。
Pythonの例外処理の基本は、tryブロックに例外が発生する可能性のある処理を書き、exceptブロックで例外を捕捉して対処するというシンプルな構造です。
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f”ゼロ除算エラーが発生しました: {e}”)
Pythonの例外クラスはすべてBaseExceptionを継承しており、アプリケーションコードで扱う例外はほとんどExceptionクラスの派生クラスです。
ZeroDivisionError・FileNotFoundError・ValueError・TypeErrorなど、組み込みの例外クラスが豊富に用意されています。
複数の例外をexceptで処理する
Pythonでは複数のexceptブロックを記述することで、種類別に異なる処理ができます。
try:
value = int(input(“数値を入力してください: “))
result = 10 / value
except ValueError:
print(“数値以外の入力です”)
except ZeroDivisionError:
print(“ゼロは入力できません”)
except Exception as e:
print(f”予期しないエラー: {e}”)
1つのexceptで複数の例外をまとめて処理したい場合はタプル形式で指定できます。
except (ValueError, TypeError) as e:
print(f”入力値エラー: {e}”)
try-except-else-finallyの完全な構文
Pythonの例外処理はtry・except・else・finallyの4つのブロックで構成できます。
try:
f = open(“data.txt”, “r”)
content = f.read()
except FileNotFoundError as e:
print(f”ファイルが存在しません: {e}”)
else:
# 例外が発生しなかった場合のみ実行される
print(f”ファイル内容: {content}”)
finally:
# 必ず実行される(例外発生の有無にかかわらず)
print(“処理を終了します”)
elseブロックはPython独自の機能であり、tryブロックが正常に完了した場合のみ実行されます。
「成功時のみ行う処理」をtryブロックとは分離して書けるため、コードの意図が明確になります。
finallyブロックはJavaと同様、ファイルのクローズやリソースの解放に使います。
raiseとカスタム例外クラスの実装
続いては、Pythonでraiseキーワードを使って例外を発生させる方法と、カスタム例外クラスの実装方法を確認していきます。
raiseを使いこなすことで、意図的に例外を発生させて処理フローをコントロールできます。
raiseによる例外の発生
raiseは例外を明示的に発生させるキーワードです。
def set_age(age):
if age < 0:
raise ValueError(f”年齢に負の値は設定できません: {age}”)
return age
try:
set_age(-1)
except ValueError as e:
print(e) # 年齢に負の値は設定できません: -1
catchブロック内で「raise」のみを記述すると、捕捉した例外をそのまま再発生(再スロー)させることができます。
try:
risky_operation()
except ValueError as e:
logging.error(f”バリデーションエラー: {e}”)
raise # 例外を再発生させて呼び出し元に伝播させる
カスタム例外クラスの作成
Pythonでは、Exceptionクラスを継承してカスタム例外クラスを定義することが推奨されます。
class InsufficientFundsError(Exception):
“””残高不足を表す例外クラス”””
def __init__(self, balance, amount):
self.balance = balance
self.amount = amount
super().__init__(
f”残高不足: 残高{balance}円に対して{amount}円の引き出し要求”)
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(balance, amount)
return balance – amount
カスタム例外クラスを使うことで、例外に業務的な意味(残高不足・認証エラーなど)を持たせることができ、コードの可読性と保守性が大幅に向上します。
例外クラスの階層設計
大規模なアプリケーションでは、アプリケーション固有の基底例外クラスを定義し、その下に具体的なカスタム例外クラスを作成する階層設計が一般的です。
class AppError(Exception):
“””アプリケーション共通の基底例外”””
pass
class DatabaseError(AppError):
“””データベース関連の例外”””
pass
class AuthenticationError(AppError):
“””認証関連の例外”””
pass
この設計により「except AppError」でアプリケーション固有のすべての例外を一括捕捉したり、「except DatabaseError」でDB関連のみを捕捉したりといった柔軟なエラーハンドリングが実現できます。
Pythonの例外処理のベストプラクティスと注意点
続いては、Pythonで例外処理を実装する際のベストプラクティスと、よくある落とし穴について確認していきます。
Pythonにはプログラミングスタイルに関して「Pythonic(Pythonicなコード)」という概念があり、例外処理にもPythonらしい書き方が存在します。
EAFP(許可より許容)スタイル
PythonではEAFP(Easier to Ask Forgiveness than Permission)というスタイルが推奨されています。
「事前に条件を確認する(LBYL:Look Before You Leap)」よりも「実行してみて例外が出たら対処する」という考え方です。
| スタイル | 特徴 | コード例 |
|---|---|---|
| LBYL(事前確認) | 条件分岐で事前チェック | if key in dict: value = dict[key] |
| EAFP(事後処理) | try-exceptで対処 | try: value = dict[key] except KeyError: … |
EAFPスタイルはPythonicとされており、特にコンテキストマネージャ(withステートメント)と組み合わせることで効果的です。
contextlibとsuppressを使った例外の無視
特定の例外を無視したい場合、空のexceptブロックではなくcontextlib.suppressを使うとPythonicです。
from contextlib import suppress
with suppress(FileNotFoundError):
os.remove(“temp.txt”) # ファイルがなくてもエラーにしない
これにより「このエラーは意図的に無視する」という意図がコード上に明示され、可読性が高まります。
loggingモジュールによる例外記録
本番コードでは例外情報を適切にログに記録することが重要です。
Pythonのloggingモジュールを使うと、スタックトレースも含めた詳細なエラー情報を記録できます。
import logging
logging.basicConfig(level=logging.ERROR)
try:
risky_function()
except Exception as e:
logging.exception(“予期しないエラーが発生しました”) # スタックトレースも自動記録
logging.exception()はexceptブロック内で使うと自動的にスタックトレースを含めてログに記録するため、エラー原因の追跡に非常に有効です。
まとめ
本記事では、例外処理のPythonでの書き方、try-except・finally・else・raise・カスタム例外・Exception処理などについて解説しました。
Pythonの例外処理はtry-except-else-finallyという4ブロック構造が基本であり、raiseによる明示的な例外発生とカスタム例外クラスの定義を組み合わせることで、堅牢なエラーハンドリングが実現できます。
EAFPスタイルやcontextlib.suppressなどのPythonic な方法を習得することで、よりクリーンで保守性の高いコードが書けるようになるでしょう。
本番コードにはloggingモジュールを活用したエラー記録を加えることで、問題発生時の調査と対応が大幅にスムーズになります。
例外処理を丁寧に実装することは、Pythonプログラムの品質と信頼性を大きく高める重要な習慣です。