Pythonのtryによる例外処理の仕組みとエラーハンドリングの使い方をわかりやすく解説

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
~
ad. 価格範囲を指定して商品を探せます

tryの概要

例外処理(エラーハンドリング)によるクラッシュ防止 Python予約語

try

概要 try(トライ)は、Pythonにおいて「例外処理(エラーハンドリング)」を実行するための最も重要な起点キーワードです。ネットワークの切断、ファイルの消失、ユーザーによる不正な値の入力など、プログラム実行中に避けられない「予期せぬエラー(例外)」を事前に想定・包囲し、システムが突然真っ赤な画面を出して強制終了(クラッシュ)するのを完全に防止する防壁を構築します。

わかりやすく説明 try は、プログラムの中に設置する「エアバッグ付きのテストゾーン(実験室)」です。「エラーでクラッシュするかもしれないけれど、とりあえずこの処理を試しに(try)やってみて!」とコンピュータに指示を出します。もしその実験が失敗(エラー発生)しても、システムを壊すことなく、隣に控える except(救済ルート)や finally(後片付け役)が衝撃を吸収し、安全に事後処理を引き受ける仕組みを作ることができます。

  • try のインデントブロック内に、ファイル読み込みや外部通信、複雑な計算などの「不確定要素を含む危険な処理」を閉じ込めます。
  • ブロック内で例外が発生した瞬間、それ以降の行の処理を即座に破棄し、該当するエラー専用の except ブロックへテレポート(避難)させます。
  • else(大成功時のみ)や finally(成否不問の絶対実行)を連結することで、システムの生存ルートを精密に設計できます。

tryの考え方をイメージで理解

try-exceptの基本的な使い方

プログラムを一発で強制終了させてしまう代表格である「0での割り算」を try-except で囲み、安全に受け流す基本形です。

# try-except を使ったエラーハンドリング
try:
    result = 10 / 0  # ⚠️ここで「ZeroDivisionError」が発生!
except ZeroDivisionError:
    # 発生したエラーの種類が一致したため、この救済ブロックへ即座にジャンプします
    print("エラー: 0で割り算をすることはできません。")

print("プログラムは強制終了せず、無事に後続の処理を続けています。")
  • 本来ならシステムがクラッシュして以降の全コードが停止する場面ですが、try の防護壁があるため、安全にエラー出力を制御できています。

特定の例外(エラーの種類)を狙ってキャッチする

エラーにはデータの種類が原因の ValueError や、ファイル不足の FileNotFoundError など、明確な「名前(型)」があります。これらを狙い撃ちして個別の対策を記述します。

# アルファベットを数値に変えようとした場合
try:
    x = int("abc")  # 数値変換に失敗し「ValueError」が発生
except ValueError:
    print("エラー: 入力された文字列を数値に変換できませんでした。")

複数の例外をまとめて処理する

ユーザーの入力ミスなど、1つの行動から複数の異なる種類のエラーが懸念される場合は、丸括弧 () のタプル形式を使って1つの窓口で一括回収できます。

# 複数のエラーを1箇所で待ち構える
try:
    num = int(input("分母となる数値を入力してください: "))
    result = 10 / num
except (ValueError, ZeroDivisionError) as e:
    # 文字の入力(ValueError)でも、0の入力(ZeroDivisionError)でも、どちらでもここに集結します
    print(f"入力または計算に問題がありました。詳細な理由: {e}")

すべての例外を網羅してキャッチする(大捕集)

どんな未知のバグや想定外のエラーが起きても絶対に落としたくないミッションクリティカルな場面では、すべてのエラーの親玉(基底クラス)である Exception を使って全回収します。

# あらゆる標準エラーをまとめて捕まえる
try:
    # 未知の通信障害や、予想もしていない深刻なバグが起きたと仮定
    value = 10 / 0
except Exception as e:
    # 個別のエラー名を知らなくても、すべてを「e」に格納して安全に回収
    print(f"予期せぬ例外を安全に検知・回収しました: {e}")

finallyで「成否に関わらず必ず実行する処理」を記述

finally を終端に付け足すと、try ブロックの実験が「大成功しようが」「エラーで大失敗しようが」、最後に必ず絶対に通過する確定クリーンアップルートを作ることができます。

# finally を使った安全なリソースの後片付け
try:
    file = open("sample.txt", "r", encoding="utf-8")
    content = file.read()
except FileNotFoundError:
    print("ファイルが存在しませんでした。")
finally:
    # 成功して読み込めようが、失敗してFileNotFoundErrorになろうが、このエリアは『絶対に』実行されます
    print("リソースクリーンアップ処理(finally)を執行しました。")

elseで「エラーが全くなかった場合」の処理を分離

else ブロックを挟むと、「try の中身が1つの傷もなく、完璧に大成功したときだけ実行したいご褒美コード」を、エラー対策コードと美しく切り分けることができます。

# else を使った成功ルートの分離
try:
    num = int(input("数値を入力: "))
    result = 10 / num
except (ZeroDivisionError, ValueError):
    print("入力に問題があったため、処理を中断しました。")
else:
    # エラーが1回も起きなかったときだけ、このルートを通過します
    print(f"計算に成功しました! 結果は {result} です。")

tryの注意点

  • except: passによるエラーの無条件隠蔽は絶対禁止のアンチパターン(超重要):実務やチーム開発において最も嫌われる最悪のコードが、except: pass(エラーが起きたのに何もせず、無言で揉み消す)という記述です。これを行うと、タイポ(記述ミス)や致命的なバグがシステム内部に完全に隠蔽され、どこが壊れているのか一切追跡できない「ゾンビプログラム」が誕生します。エラーをキャッチした際は、最低限ログに吐き出すか画面に出力して原因を可視化するのがプロの絶対ルールです。
    # 【最悪の失敗コード:バグが闇に葬られ、アプリが原因不明の挙動になります】
    try:
        result = user_data.caclulate_score() # タイポ(正しくは calculate_score)
    except Exception:
        pass # エラーを無視するため、タイポに永遠に気づけなくなります!
    
    # 【健全な対策コード】
    try:
        result = user_data.calculate_score()
    except Exception as e:
        # 最低限、何が起きたかを開発者に知らせる防衛線を張る
        print(f"【システムログ】エラーを検知しました: {e}")
        raise # 必要に応じて上位へエラーを再送する
  • tryブロックのスコープ内に大量のコードを詰め込まない:try の中に50行も100行もコードを詰め込んでしまうと、一体その中の「どの行が原因」で ValueError が起きたのかが完全に不透明になります。try で囲む範囲は、エラーを引き起こすリスクがある「ピンポイントな数行だけ」に極限まで絞り込むのが鉄則です。
    # 【範囲が広すぎる失敗コード】
    try:
        # どこの int 変換や計算でエラーが出たのか迷宮入りします
        x = int(input_data)
        user.save_to_db(x)
        send_notification_email(user)
        update_dashboard_view()
    except ValueError:
        print("値が不正です")
    
    # 【ピンポイントに絞り込んだ正しい対策コード】
    try:
        x = int(input_data) # エラーの主犯格になり得る行だけを狙い撃ち
    except ValueError:
        print("値が不正です")
        return
    
    # 安全が確定したデータを引っ提げて次の処理へ進む
    user.save_to_db(x)
    send_notification_email(user)

tryのよくある質問

Q: `try` 文を単体で使ったり、`except` や `finally` を一切書かずに `try` と `else` だけで組み合わせることは可能ですか?
A: 完全に不可能です。try を記述した場合は、直後のインデントブロックの終端に、最低でも1つの except、または finally のどちらか片方(あるいは両方)が盾としてセットで配置されていなければならず、欠けている場合はその時点で文法エラー(SyntaxError)としてPythonに弾かれます。

# 【エラーになる失敗コード】
try:
    result = 10 / 2
else: # ❌except も finally もないため、構文エラーになります
    print("成功")
Q: `except Exception as e` で指定する `as e` という記述の正体と、メリットを教えてください。
A: 「発生したエラーオブジェクトの現物を、一時的に『e』という名前の変数に格納して利用する」ための文法です。 as e(名前は err など自由に変えられます)を指定すると、そのエラーが発生した「生の理由メッセージ」が文字列のように取得できます。これを print(e) や logger.error(e) で出力させることで、「ファイルが存在しないのか」「パスワードが違うのか」という、コンピュータが検知した真の原因を人間が正確にデバッグして把握できるようになります。

まとめ

try は、想定外の事態に直面してもシステムを絶対に落とさない、アプリケーションの「生存率」を極限まで高めるための最強のディフェンスキーワードです。

  • try ブロックでエラー予備軍を厳重に囲い込み、想定されるトラブルは except の網で個別に安全回収する。
  • 大成功ルートの else、絶対清算ルートの finally を使いこなし、リソースリーク(メモリやファイルの閉じ忘れ)を未然に徹底防御する。
  • エラーを闇雲に隠蔽(揉み消し)するのではなく、適切に検知して原因をログに蓄積することが、実務における一流の例外設計の条件。

実務の現場では、Webサーバーの運用、データベースのトランザクション制御、スクレイピングによる外部データの回収など、あらゆるインフラ構築の最前線で try が守護神として稼働しています。防衛ロジックのメカニズムを完璧に支配し、ユーザーに不安を与えない頑丈なシステムへと昇華させましょう。