一覧へ

Python 例外処理 — try, except, raise

Python でエラーを捕捉、発生、処理する方法。例外処理のすべてを実践的な例で学びます。

中級
|
10
|
検証済み (2026-07)
例外処理try-exceptraisefinallyエラーハンドリング
進捗0/18 (0%)

Python の例外処理 — try、except、raise

このトピックを完了すると、次のことが理解できるようになります。

Python でエラーがどのように発生するか、try/except を使用してエラーをどのようにキャッチするか、raise を使用してエラーを直接発生させる方法、および finally を使用してクリーンアップ操作を実行する方法を理解します。


エラーはプログラムを停止させる

Python では、エラーが発生すると、プログラムは直ちに停止します。

python
numbers = [1, 2, 3]
print(numbers[10]) # IndexError: list index out of range
print("This line never runs")

エラーが発生した行以降のすべてのコードは実行されません。Web サーバーの場合、サーバー自体がクラッシュします。データ分析スクリプトの場合、1000 個の項目のうち 999 個を処理した後、完全に失敗します。

例外処理は、「プログラムがクラッシュすることなくエラーを処理する方法」です。


try/except — エラーのキャッチ

python
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero")
print("Program continues") # この行は実行されます!

try ブロック内でエラーが発生した場合、プログラムは except ブロックにジャンプします。プログラムは停止せず、実行を継続します。

エラーメッセージの取得

python
try:
value = int("hello")
except ValueError as e:
print(f"Error: {e}") # Error: invalid literal for int() with base 10: 'hello'

as e を使用すると、エラーオブジェクトを受け取り、何が問題だったのかを確認できます。

複数のエラーを個別に処理する

python
def safe_divide(a, b):
try:
result = a / b
return round(result, 2)
except ZeroDivisionError:
print("Denominator cannot be zero")
return None
except TypeError:
print("Both arguments must be numbers")
return None
safe_divide(10, 0) # Denominator cannot be zero
safe_divide("10", 2) # Both arguments must be numbers
safe_divide(10, 3) # 3.33

異なるエラータイプを異なる方法で処理できます。except Exception を使用して、すべてのエラーを一度にキャッチすることもできますが、推奨されません。デバッグが難しくなるためです。エラーが発生したときに、どのエラーが発生したのかわからなくなります。


一般的なエラータイプ

エラー原因
ValueError無効な値int("abc")
TypeError不適切な型"3" + 5
IndexErrorインデックスが範囲外[1,2,3][10]
KeyError辞書のキーが存在しない{"a": 1}["b"]
FileNotFoundErrorファイルが存在しないopen("none.txt")
ZeroDivisionErrorゼロ除算10 / 0
AttributeError存在しない属性/メソッドへのアクセスNone.upper()

これらは、日常的なプログラミングで遭遇する最も一般的な 7 つのエラーです。


elsefinally

python
try:
f = open("data.txt", "r")
content = f.read()
except FileNotFoundError:
print("File not found")
else:
# try ブロックが成功した場合にのみ実行されます
print(f"Read {len(content)} characters")
finally:
# 常に実行されます(成功または失敗に関係なく)
print("Cleanup done")
ブロック実行タイミング
try常に試行
exceptエラーが発生した場合
elseエラーなしで成功した場合
finally常に(成功と失敗の両方)

finally は、ファイルやネットワーク接続を閉じたり、一時ファイルを削除したりするなど、クリーンアップ操作に使用されます。これは、エラーが発生したかどうかに関係なく、常に実行する必要があるコードです。


raise — エラーを直接発生させる

python
def withdraw(balance, amount):
if amount <= 0:
raise ValueError("Withdrawal amount must be positive")
if amount > balance:
raise ValueError(f"Insufficient funds: balance={balance}, requested={amount}")
return balance - amount
try:
new_balance = withdraw(1000, 5000)
except ValueError as e:
print(f"Transaction failed: {e}")
# Transaction failed: Insufficient funds: balance=1000, requested=5000

raise は、「この状況は通常ではない」と宣言する方法です。エラーを try/except を使用して処理する責任を呼び出し側に委譲します。

カスタムエラークラス

python
class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
self.balance = balance
self.amount = amount
super().__init__(
f"Cannot withdraw {amount} from balance {balance}"
)
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(balance, amount)
return balance - amount
try:
withdraw(1000, 5000)
except InsufficientFundsError as e:
print(e) # Cannot withdraw 5000 from balance 1000
print(e.balance) # 1000
print(e.amount) # 5000

Exception から継承して、独自のカスタムエラーを作成できます。これにより、エラーに追加情報(残高、要求額)を含めることができるため、エラー処理コードはより正確に応答できます。


実際のパターン — ファイル処理

python
def read_config(filepath):
try:
with open(filepath, "r", encoding="utf-8") as f:
lines = f.readlines()
except FileNotFoundError:
print(f"Config file not found: {filepath}")
return {}
except PermissionError:
print(f"Permission denied: {filepath}")
return {}
config = {}
for i, line in enumerate(lines, 1):
line = line.strip()
if not line or line.startswith("#"):
continue
if "=" not in line:
print(f"Warning: invalid format at line {i}: {line}")
continue
key, value = line.split("=", 1)
config[key.strip()] = value.strip()
return config
# config.txt:
# host = localhost
# port = 3000
# # this is a comment
settings = read_config("config.txt")
print(settings) # {'host': 'localhost', 'port': '3000'}

このパターンは、実際のシナリオで非常に一般的です。

  1. ファイルを開くことができない場合は、except で処理されます。
  2. 解析中に不正な行が見つかった場合は、警告のみが表示され、スキップされます。
  3. 空の行とコメント(#)は無視されます。

プログラムは、構成ファイルを開くことができないという理由だけでクラッシュするのではなく、デフォルト値で動作するか、警告を表示します。


アンチパターン — してはいけないこと

すべてのエラーを無視する

python
# 悪い — エラーを飲み込む
try:
risky_operation()
except Exception:
pass # 何が起こったのか?誰も知らない
# 良い — 少なくともログに記録する
try:
risky_operation()
except Exception as e:
print(f"Warning: {e}") # または logging.warning(...)

except: pass は、すべてのエラーを無視します。プログラムはクラッシュしませんが、何が問題だったのかわかりません。後でデバッグするのが非常に難しくなります。

広すぎる except

python
# 悪い — タイプミス(NameError)をキャッチする
try:
valeu = int(input("Enter number: ")) # タイプミス: valeu
except Exception:
print("Invalid input") # NameError だが、"Invalid input" なのか?
# 良い — 予想されるエラーのみをキャッチする
try:
value = int(input("Enter number: "))
except ValueError:
print("Invalid input — please enter a number")

主要なポイント

構文役割使用するタイミング
tryエラーが発生する可能性のあるコードをラップする外部入力、ファイル、ネットワークなど
except特定のエラーをキャッチして処理する各エラータイプに対して異なる処理が必要な場合
else成功した場合にのみ実行するエラーが発生しなかった場合に実行する追加のアクション
finally常に実行するクリーンアップ操作(ファイルのクローズ、接続の終了)
raiseエラーを直接発生させる無効な入力、ビジネスルールの違反

例外処理の主な原則:予想されるエラーのみをキャッチし、できるだけ狭くキャッチし、無視しないこと。 すべてを try/except でラップすると安全になるという考え方は誤りです。不適切な例外処理は、エラーを隠し、例外がない場合よりもデバッグをさらに困難にする可能性があります。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...