Pythonの例外処理のアンチパターン5選をご紹介!|初心者がやりがちな「べからず集」
Pythonをブラウザで実行しながら実践的に学ぶ
Pythonの基礎からソフトウェアアーキテクチャ,アルゴリズムなどの応用的な内容まで幅広く学べます。
ブラウザ上で直接Pythonコードを試すことができ、実践的なスキルを身につけることが可能です。
プログラミングを学び始めたとき、多くの人がつまずくのが例外処理です。
Pythonにはとてもシンプルで使いやすいtry-except
構文がありますが、実はなんとなくで使ってしまうと後で大きな問題になることがあります。
私はエンジニア歴10年になりますが、これまで多くの初心者コードをレビューしてきました。 その中で「うわ…これやってる人、多いな」と感じた“例外処理のアンチパターン”を5つ、今回は徹底的に紹介します。
「なんとなく動くけど、なぜか不安定」 「エラーが出ても原因がわからない」 「例外処理を入れたら逆にバグった」
そんな経験がある人は、ぜひ最後まで読んでみてください。 この記事を読み終える頃には、「正しい例外処理の書き方」がきっと腑に落ちるはずです。
そもそも「例外処理」ってなに?¶
まずは少しおさらいをしましょう! Pythonの例外処理は「エラーが起きたときにプログラムを止めず、安全に処理を続けるための仕組み」です。
たとえば、ユーザーが入力した文字列を数値に変換するときを見てみましょう。
try:
number = int(input("数字を入力してください: "))
print(f"あなたが入力した数字は {number} です。")
except ValueError:
print("数字以外が入力されました。もう一度試してください。")
このように書くと、ユーザーが「abc」と入力してもプログラムは止まりません。ValueError
をキャッチして、代わりにメッセージを表示します。
ただし、この便利な仕組みも使い方を間違えると“毒”になります。
次に、初心者がやりがちな「べからず集」を見ていきましょう。
アンチパターン①:except Exception:
で全部キャッチする¶
「とりあえずこれ書いておけば安心」と思っている人、多いですよね。私も昔はそうでした。
以下の例を見てみましょう。
try:
# なんかの処理
result = 10 / 0
except Exception:
print("なんかエラーが起きました!")
一見すると便利そうですが、これは最悪のアンチパターンです。
なぜかというと、どんなエラーが起きても握りつぶしてしまうからです。たとえば、ユーザーが間違えた入力をしただけならまだしも、プログラムのバグやシステムエラーまで無視してしまうこともあります。
実際に私がレビューしたコードの中で、ファイル読み込みが失敗しても、ネットワーク接続が切れても、全部このexcept Exception:
でキャッチしてしまい、「何が失敗してるのかわからない」という地獄のようなデバッグに陥ったケースがありました。
正しい書き方のポイント¶
できる限り具体的な例外をキャッチするのが鉄則です。
try:
result = 10 / 0
except ZeroDivisionError:
print("0で割ろうとしています。")
また、複数の例外が想定される場合はカンマで並べましょう。
try:
value = int("abc")
except (ValueError, TypeError):
print("型変換でエラーが発生しました。")
どんな例外が起こりうるかを明確にすることが、安心・安全なコードにつながります。
アンチパターン②:except:
だけ書く(例外クラス省略)¶
これも地味に多いパターンです。
except:
だけ書くと、すべての例外(KeyboardInterruptやSystemExitなども含む)をキャッチしてしまいます。
try:
while True:
print("Ctrl+Cで止めてください")
except:
print("止められません!")
これを実行すると、なんとCtrl+Cを押しても止まりません。強制終了すらキャッチしてしまうのです。
本当に危険なので、except:
だけで書くのは絶対に避けましょう。
修正版¶
以下のようにコードを改善しましょう!
try:
while True:
print("Ctrl+Cで止めてください")
except KeyboardInterrupt:
print("中断されました。")
こうすれば、意図した中断だけを安全に扱えます。
アンチパターン③:エラーを握りつぶす(pass
だけ)¶
初心者のコードレビューで最も多いのがこれです。
try:
risky_function()
except:
pass
「とりあえず落ちないようにしておこう」と思って書く気持ちはわかります。でも、このpass
は「エラーを完全に無視する」という意味です。
つまり、何か問題が起きても開発者自身が気づけないんです。
私が過去に遭遇した例では、あるシステムでAPIの通信エラーが発生していたにも関わらず、except: pass
が入っていたせいで、1週間分のデータが欠損していたことがありました…。
改善方法¶
せめてログを出すようにしましょう。以下のように改善します。
import logging
try:
risky_function()
except Exception as e:
logging.error(f"エラー発生: {e}")
これだけでも「どこで、どんなエラーが起きたか」がわかるようになります。
開発環境ではprint()
でも構いませんが、本番環境ではログを残す習慣をつけましょう。
アンチパターン④:例外処理を使って通常処理を制御する¶
これもよく見る「やりがちな誤用」です。
try:
value = my_dict["key"]
except KeyError:
value = "デフォルト"
一見するとスマートに見えますが、実はこれはパフォーマンス的にも設計的にも悪手です。 try-except
は「例外が起こるかもしれない箇所」に限定して使うべきで、
「普通に存在しない可能性がある」なら条件分岐で処理したほうがいいのです。
よりよい書き方¶
value = my_dict.get("key", "デフォルト")
このように、Pythonにはちゃんと便利な方法が用意されています。 例外処理は「想定外の事態」に使う。これが基本です。
アンチパターン⑤:例外をキャッチしたあと何もしない or 再スローしない¶
最後は少し上級者向けですが、とても大事なポイントです。
例えば次のようなコードを見てみましょう。
def process_data():
try:
read_data()
validate_data()
save_data()
except ValueError as e:
print(f"データの形式が不正: {e}")
一見正しく見えますが、ここで処理を終わらせてしまうと「上位の呼び出し元」にエラーが伝わりません。もし上位でログを記録したり、再試行したりする仕組みがある場合、例外を止めてしまうのは良くないのです。
正しいパターン¶
def process_data():
try:
read_data()
validate_data()
save_data()
except ValueError as e:
print(f"データの形式が不正: {e}")
raise # 再スロー
raise
だけ書くことで、同じ例外を上位に投げ直すことができます。
これをしておくと、アプリ全体で一貫したエラーハンドリングが可能になります。
アンチパターン5選まとめ¶
ここまで紹介したアンチパターンをまとめておきましょう。
No. | アンチパターン | 問題点 | 改善方法 |
---|---|---|---|
1 | except Exceptionで全部キャッチ | バグや重要なエラーを隠す | 具体的な例外を指定する |
2 | except: だけ | システム終了すら止めてしまう | 必要な例外を明示的に書く |
3 | except後にpassだけ | エラーを無視して気づけない | ログを出力する |
4 | 例外処理を通常処理に使う | パフォーマンス悪化、設計が不明瞭 | if文やget()を使う |
5 | 例外を再スローしない | 上位にエラーが伝わらない | raise で再送出する |
例外処理は「優しさ」ではなく「責任」¶
初心者がやりがちなミスの多くは、「優しさ」から来ています。
「落ちたら困るから」「ユーザーに迷惑かけたくないから」
そう思って何でもキャッチしてしまう。でも、それが逆にトラブルを隠してしまうんです。
エンジニアとして大切なのは、問題を隠すことではなく、早く気づけるようにすること。エラーを正しく扱うことは、ユーザーにも、将来の自分にも優しいコードを書くことにつながります。
まとめ:例外処理は“怖くない”、けれど“甘くもない”¶
例外処理は、初心者が最初に「魔法のように便利」と感じる機能の一つです。 しかし、扱いを間違えると、コードの信頼性を大きく損なうリスクもあります。
私自身、10年の現場経験を通して「例外処理の怖さ」と「ありがたさ」の両方を学びました。 ぜひあなたも、今日紹介したアンチパターンを避けて、正しく美しい例外処理を書けるエンジニアを目指してください。
この記事を読んで「自分のコード、やってたかも…」と思った人は、ぜひ一度、自分のプロジェクトの中のtry-except
を見直してみましょう。
その一歩が、バグの少ない・信頼されるコードへの第一歩です。
ここまでお読みいただきありがとうございました!