🤐 例外の黙殺(Errors should never pass silently)
🧭 はじめに
このページでは、Python の Zen Errors should never pass silently に真正面から反するアンチパターン、 「例外の黙殺」 を扱います。
例外の黙殺は「とりあえず落ちないようにする」ための小細工に見えますが、 実際には バグを不可逆に埋め込み、後工程で爆発させる設計ミスです。
🎯 ねらい
except: passがなぜ危険なのかを構造的に説明する- 「無視する例外」と「握りつぶしているだけの例外」を区別する
❓ 問題の定義
例外の黙殺とは、
- 例外が発生しているにもかかわらず
- 何も記録せず、何も通知せず
- 処理を成功したかのように継続する
設計を指します。
例外を握りつぶすと、異常状態が「正常データ」に偽装されます。
🤒 よくある症状
🙈 bare except
try:
do_something()
except:
pass
- 何が起きたか分からない
- どの例外を想定しているか不明
- 将来の変更で別の例外が混入しても検知不能
📭 ログもメトリクスもない
- エラーが発生しても痕跡が残らない
- 再現不能な「たまに壊れる」障害になる
🎭 失敗したのに成功した体で流す
- 初期化失敗 → デフォルト値で継続
- 読み込み失敗 → 空データで続行
→ 失敗の影響が下流で増幅する。
黙殺された例外は、その場では小さく見えても、後で必ず高くつきます。
❌ 悪い例:設定読み込み失敗を黙殺
def load_config(path):
try:
with open(path) as f:
return json.load(f)
except Exception:
return {}
何が起きるか
- ファイル不存在
- JSON 破損
- 権限エラー
すべて同じ {} に潰される。
結果として、
- 本番で 意図しないデフォルト設定が有効化
- セキュリティ・性能・課金で事故
✅ 良い例①:例外を限定する
def load_config(path):
try:
with open(path) as f:
return json.load(f)
except FileNotFoundError:
log_error(f'config not found: {path}')
raise
改善点
- 想定している失敗だけを捕捉
- 想定外はそのまま上に伝播
- ログにより原因が観測可能
✅ 良い例②:「無視する」を仕様にする
def load_optional_config(path):
try:
with open(path) as f:
return json.load(f)
except FileNotFoundError:
# optional config is allowed to be missing
log_info(f'optional config not found: {path}')
return None
ポイント
- 無視する理由がコメントで明示
- 呼び出し側が
Noneを契約として扱える - 振る舞いが設計として読める
「無視する」は例外ではなく仕様です。仕様なら説明責任があります。
🧩 設計の要点
例外処理で最低限守ること
-
例外型を絞る 何を想定しているのかをコードで示す
-
観測可能性を残す ログ・メトリクス・カウンタ
-
下流に嘘を流さない 失敗したなら、失敗したと分かる形で返す
✅ チェックリスト
except Exception:や bare except を使っていないか- 捕捉している例外は 本当に想定内か
- 無視する理由が コメントで説明されているか
- 最低限のログ/メトリクスがあるか
`except:`(bare except)は原則禁止を チーム規約として明文化するのが効果的です。
🧠 まとめ
例外の黙殺は、
- 落ちない安心感
- 今すぐの静けさ
と引き換えに、
- 原因不明の障害
- 調査不能な事故
を未来に押し付けます。
Python の Zen が言う Errors should never pass silently とは、
落とせ、という意味ではない 失敗を観測可能にせよという設計原則
です。
次の記事では、 その「曖昧さを条件式に持ち込む」アンチパターン 🧠 推測に頼るコードを扱います。