0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Python] 例外処理 try / except / else / finally / raise

0
Last updated at Posted at 2026-08-06

Pythonの例外処理を理解する:tryexceptasraiseの基本

概要

Pythonでは、プログラムの実行中に発生した問題を例外として表現します。

例えば、次の処理では、文字列を整数に変換できないため ValueError が発生します。

int("abc")

例外処理では、主に次の構文を使用します。

構文 役割
try 例外が発生する可能性のある処理を書く
except 発生した例外を捕捉して処理する
as 発生した例外インスタンスを変数で受け取る
else 例外が発生しなかった場合に実行する
finally 例外の有無にかかわらず実行する
raise 意図的に例外を発生させる

例外処理は、エラーを隠すためではなく、異常な状態を適切な場所へ伝え、処理方法を分離するために使用する。

実施条件

  • Pythonの関数を理解していること
  • クラスとインスタンスの基本を理解していること
  • if文による条件分岐を理解していること

環境

ツール バージョン 目的
Python 3.12 Pythonコードの実行
VS Code 任意 コード編集

Pythonの例外とは

例外は、プログラムの実行を通常どおり続けられない状態を表します。

number = int("abc")

実行すると、次のような例外が発生します。

ValueError: invalid literal for int() with base 10: 'abc'

例外が捕捉されなければ、通常はその時点で処理が中断され、トレースバックが表示されます。

例外もクラスである

ValueError は、Pythonに組み込まれた例外クラスです。

error = ValueError("値が不正です")

error は、ValueError クラスのインスタンスです。

print(type(error))
# <class 'ValueError'>

print(isinstance(error, ValueError))
# True

print(isinstance(error, Exception))
# True

例外の大まかな継承関係は、次のようになっています。

BaseException
├── KeyboardInterrupt
├── SystemExit
└── Exception
    ├── TypeError
    ├── ValueError
    ├── LookupError
    │   ├── KeyError
    │   └── IndexError
    ├── OSError
    │   └── FileNotFoundError
    └── RuntimeError

通常のアプリケーションで扱う例外の多くは、Exception を継承しています。

代表的な組み込み例外

TypeError

処理対象の型が不適切な場合に発生します。

"100" + 20
# TypeError

関数内で型を検証して発生させることもできます。

def set_price(price: int) -> None:
    if not isinstance(price, int):
        raise TypeError(
            "priceは整数で指定してください"
        )

ValueError

型は適切でも、値の内容が不正な場合に発生します。

int("abc")
# ValueError
def set_price(price: int) -> None:
    if price < 0:
        raise ValueError(
            "priceは0以上で指定してください"
        )

TypeErrorValueError の違いは次のとおりです。

状態 使用する例外
値の型が不適切 TypeError
型は正しいが値が不適切 ValueError

KeyError

辞書に存在しないキーを参照した場合に発生します。

product = {
    "name": "Python入門",
}

print(product["price"])
# KeyError: 'price'

IndexError

リストやタプルの範囲外を参照した場合に発生します。

items = [1, 2, 3]

print(items[10])
# IndexError

FileNotFoundError

存在しないファイルを開こうとした場合に発生します。

open("missing.txt")
# FileNotFoundError

tryexcept

例外が発生する可能性のある処理を try に書きます。

例外が発生した場合の処理を except に書きます。

raw_value = "abc"

try:
    number = int(raw_value)
except ValueError:
    print("整数へ変換できませんでした")

出力:

整数へ変換できませんでした

処理の流れは次のとおりです。

tryブロックを実行
    ↓
例外が発生したか
    ├── しなかった → exceptを飛ばす
    └── 発生した   → 一致するexceptを探す

except ... as exc

as を使用すると、発生した例外インスタンスを変数で受け取れます。

try:
    number = int("abc")
except ValueError as exc:
    print(exc)

出力:

invalid literal for int() with base 10: 'abc'

ここでの各要素は、次の役割を持ちます。

要素 意味
ValueError 捕捉する例外クラス
as 例外インスタンスに変数名を付ける
exc 発生した例外インスタンス

exc は一般的な命名であり、別の名前でも構いません。

except ValueError as error:
    print(error)

ただし、exc または error がよく使われます。

as excだけでは表示されない

次のコードでは、例外インスタンスを exc で受け取っていますが、何も表示していません。

try:
    int("abc")
except ValueError as exc:
    pass

as exc は、例外を自動的に表示する構文ではありません。

表示する場合は、明示的に print() します。

print(exc)

ログに記録する場合は、ロガーへ渡します。

import logging

logger = logging.getLogger(__name__)

try:
    int("abc")
except ValueError as exc:
    logger.exception(
        "整数への変換に失敗しました"
    )

例外インスタンスの内容

try:
    int("abc")
except ValueError as exc:
    print(type(exc))
    print(str(exc))
    print(exc.args)

出力例:

<class 'ValueError'>
invalid literal for int() with base 10: 'abc'
("invalid literal for int() with base 10: 'abc'",)
記述 内容
type(exc) 例外インスタンスのクラス
str(exc) 例外メッセージ
exc.args 例外生成時に渡された引数

複数のexcept

発生する可能性がある例外ごとに、異なる処理を書けます。

def get_product_price(
    product: dict[str, str],
) -> int:
    try:
        return int(product["price"])

    except KeyError:
        print("priceキーがありません")

    except ValueError:
        print("priceを整数へ変換できません")

    return 0
get_product_price({})
# priceキーがありません
get_product_price({"price": "三千円"})
# priceを整数へ変換できません

複数の例外をまとめて捕捉する

同じ処理を行う場合は、タプルで複数の例外を指定できます。

try:
    price = int(product["price"])
except (KeyError, ValueError) as exc:
    print(f"商品価格を取得できません: {exc}")

exceptの順番

例外クラスには継承関係があるため、具体的な例外から先に記述します。

try:
    int("abc")

except ValueError:
    print("値が不正です")

except Exception:
    print("その他の例外です")

次の順番は適切ではありません。

try:
    int("abc")

except Exception:
    print("例外が発生しました")

except ValueError:
    print("値が不正です")

ValueErrorException のサブクラスです。

そのため、最初の except Exception ですでに捕捉され、後ろの except ValueError には到達しません。

raise

raise は、プログラム側から意図的に例外を発生させる構文です。

raise ValueError("値が不正です")

関数内の入力検証でよく使用します。

def calculate_discount(
    price: int,
    discount_rate: float,
) -> int:
    if price < 0:
        raise ValueError(
            "priceは0以上で指定してください"
        )

    if not 0 <= discount_rate <= 1:
        raise ValueError(
            "discount_rateは0以上1以下で指定してください"
        )

    return round(price * (1 - discount_rate))
calculate_discount(3000, 1.5)
# ValueError

例外クラスと例外インスタンス

次のどちらも使用できます。

raise ValueError
raise ValueError()

メッセージを渡す場合は、例外インスタンスを生成して送出します。

raise ValueError(
    "価格は0以上で指定してください"
)

原因を確認しやすくするため、通常は具体的なメッセージを付けます。

引数なしのraise

except ブロック内で、引数を指定せずに raise すると、現在処理中の例外をそのまま再送出します。

def parse_price(raw_price: str) -> int:
    try:
        return int(raw_price)

    except ValueError as exc:
        print(f"価格変換に失敗しました: {exc}")
        raise
try:
    parse_price("三千円")
except ValueError:
    print("呼び出し元で例外を処理しました")

処理の流れは次のとおりです。

int()でValueError
    ↓
parse_price()内のexcept
    ↓
ログや補助処理
    ↓
raiseで同じValueErrorを再送出
    ↓
呼び出し元のexcept

ログを記録したうえで、処理自体は上位層に任せたい場合に利用できます。

else

else は、try 内で例外が発生しなかった場合に実行されます。

try:
    price = int("3000")
except ValueError as exc:
    print(f"変換失敗: {exc}")
else:
    print(f"変換成功: {price}")

出力:

変換成功: 3000

次のように、例外が発生する可能性のある処理だけを try に含められます。

try:
    price = int(raw_price)
except ValueError as exc:
    print(f"変換失敗: {exc}")
else:
    save_price(price)

save_price() で発生した例外まで、誤って ValueError として処理することを避けられます。

finally

finally は、例外が発生したかどうかにかかわらず実行されます。

try:
    price = int("3000")
except ValueError:
    print("変換失敗")
finally:
    print("処理を終了します")

出力:

処理を終了します

リソースの解放などに使用できます。

file = open("sample.txt", encoding="utf-8")

try:
    content = file.read()
finally:
    file.close()

ただし、ファイル操作では通常、with を使う方が簡潔です。

with open("sample.txt", encoding="utf-8") as file:
    content = file.read()

tryexceptelsefinally

完全な構造は次のとおりです。

try:
    price = int("3000")

except ValueError as exc:
    print(f"変換失敗: {exc}")

else:
    print(f"変換成功: {price}")

finally:
    print("処理終了")
ブロック 実行条件
try 最初に実行される
except 対象の例外が発生した場合
else 例外が発生しなかった場合
finally 原則として必ず実行される

避けるべき例外処理

例外の握りつぶし

try:
    process()
except Exception:
    pass

このコードでは、例外が発生しても何も記録されません。

障害の発見や原因調査が難しくなります。

少なくともログを記録するか、再送出します。

try:
    process()
except ValueError as exc:
    print(f"処理に失敗しました: {exc}")
    raise

裸のexcept

try:
    process()
except:
    print("エラー")

例外クラスを省略すると、KeyboardInterruptSystemExit なども捕捉する可能性があります。

可能な限り、具体的な例外を指定します。

except ValueError:

複数の通常例外を最後にまとめて処理する必要がある場合は、Exception を指定します。

except Exception as exc:

ただし、広範囲な Exception の捕捉は、アプリケーションの最上位層など、責任範囲が明確な場所に限定します。

tryの範囲が広すぎる

try:
    price = int(raw_price)
    product = create_product(price)
    save_product(product)
    send_notification(product)
except ValueError:
    print("値が不正です")

どの処理で ValueError が発生したのか分かりにくくなります。

例外が想定される範囲を小さくします。

try:
    price = int(raw_price)
except ValueError as exc:
    print(f"価格が不正です: {exc}")
    return

product = create_product(price)
save_product(product)
send_notification(product)

活用例:商品価格の変換

def parse_price(raw_price: str) -> int:
    try:
        price = int(raw_price)

    except ValueError as exc:
        print(
            f"価格を整数へ変換できません: {exc}"
        )
        raise

    else:
        if price < 0:
            raise ValueError(
                "価格は0以上で指定してください"
            )

        return price

    finally:
        print("価格変換処理を終了しました")
try:
    result = parse_price("3000")
except ValueError as exc:
    print(f"入力エラー: {exc}")
else:
    print(f"変換結果: {result}")

出力:

価格変換処理を終了しました
変換結果: 3000

まとめ

  • 例外は、通常処理を継続できない状態を表すオブジェクト
  • ValueErrorTypeError などもクラスである
  • try に例外が発生する可能性のある処理を書く
  • except で特定の例外を捕捉する
  • as exc は、例外インスタンスを変数として受け取る
  • as exc だけでは、例外は表示されない
  • print(exc) やロガーを使って、例外内容を出力する
  • raise により意図的に例外を発生させられる
  • 引数なしの raise は、現在の例外を再送出する
  • else は例外がなかった場合に実行される
  • finally は例外の有無にかかわらず実行される
  • 例外は具体的なクラスから捕捉する
  • 例外を何もせず握りつぶす処理は避ける

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?