Python / LESSON 10 / PY10

Python:例外処理(try / except / finally)

1学習の目的

2基礎解説

やりたいこと書き方意味
エラーを受け止めるtry: / except:エラーが起きても止まらない
種類ごとに対応except ValueError:指定した種類だけを捕まえる
内容を受け取るexcept Exception as e:e にエラーメッセージが入る
必ず実行するfinally:成功・失敗どちらでも実行
✅ 覚えるべき重要ポイント
  1. try の中でエラーが起きると、その行以降は飛ばして except へ移る。プログラム自体は止まらない。
  2. よく出るエラー:ValueError(int("abc"))、ZeroDivisionError(0で割る)、KeyError(辞書のキーなし)、TypeError(型が違う)。
  3. 裸の except: は書かない。想定外のエラーまで握りつぶして、バグの原因が分からなくなる。必ず種類を指定する。
  4. finally: は成功でも失敗でも必ず実行される。ファイルを閉じるなどの後始末に使う。
  5. raise ValueError("メッセージ")自分からエラーを出せる。不正なデータを見つけたら、その場で raise して呼び出し元に知らせるのが正しい設計。

現場使用例:ユーザー入力の数値変換、APIリクエストの失敗、ファイルが見つからない、CSVの不正行スキップ、設定値の欠損。外部から来るデータを扱う処理には必ず必要

value = "abc"

try:
    num = int(value)
    print(f"変換成功:{num}")
except ValueError:
    print("数値に変換できません")
finally:
    print("処理を終了しました")

# エラーの内容を受け取る
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"エラー内容:{e}")   # division by zero

3基本ドリル(10問)

PY10-D01 value = "abc" を int() で数値に変換し、失敗したら「数値に変換できません」と出力せよ。 コーディング★☆☆無料
期待される結果

出力 == 数値に変換できません

ヒント

try: の中で変換し、except ValueError: で受け止める。

模範解答
value = "abc"

try:
    num = int(value)
    print(num)
except ValueError:
    print("数値に変換できません")
解説

try/exceptの最小形。except が無ければここでプログラムは停止する。外部データを扱うときの基本の型。

PY10-D02 10 / 0 を実行したとき発生するエラーはどれか。
A. ValueError B. ZeroDivisionError C. TypeError D. KeyError
選択★☆☆無料
期待される結果

解答 == B

ヒント

エラー名がそのまま内容を表している。

模範解答
B
解説

Pythonのエラー名は内容をそのまま表す。エラーが出たらまず名前を読むのが解決への最短ルート。

PY10-D03 a = 10, b = 0 のとき a ÷ b を計算し、0で割ろうとしたら「0では割れません」と出力せよ。 コーディング★☆☆無料
期待される結果

出力 == 0では割れません

ヒント

except ZeroDivisionError: で受け止める。

模範解答
a = 10
b = 0

try:
    print(a / b)
except ZeroDivisionError:
    print("0では割れません")
解説

平均を計算するときにデータが0件だとこのエラーが出る。集計処理では必ず考慮すべき定番のケース。

PY10-D04 変換に失敗したら「失敗」と出力するコードを完成させよ。 穴埋め★☆☆無料
コード
try:
    num = int("あ")
____ ValueError:
    print("失敗")
期待される結果

出力 == 失敗

ヒント

エラーを受け止めるキーワード。末尾のコロンも忘れずに。

模範解答
except ValueError:
解説

except の後ろにエラーの種類を書く。コロンとインデントは if や for と同じルール。

PY10-D05 finally: ブロックはいつ実行されるか。
A. エラーが起きたときだけ B. エラーが起きなかったときだけ C. どちらの場合も必ず D. 実行されない
選択★☆☆無料
期待される結果

解答 == C

ヒント

名前のとおり「最後に必ず」。

模範解答
C
解説

成功・失敗にかかわらず実行される。ファイルや通信の後始末など絶対にやり残せない処理を書く場所。

PY10-D06 10 ÷ 0 を実行し、エラーの内容を「エラー内容:division by zero」の形式で出力せよ。 コーディング★★☆無料
期待される結果

出力 == エラー内容:division by zero

ヒント

except ZeroDivisionError as e: と書くと e にエラー内容が入る。

模範解答
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"エラー内容:{e}")
解説

as e で内容を取り出せる。実務ではこれをログに記録して、後から原因を追えるようにする。

PY10-D07 成功しても失敗しても最後に「終了」と出力するコードを完成させよ。 穴埋め★★☆無料
コード
try:
    print("処理中")
except ValueError:
    print("失敗")
____:
    print("終了")
期待される結果

出力 == 処理中 / 終了(2行)

ヒント

「最後に必ず」を表すキーワード。

模範解答
finally:
解説

この例ではエラーが起きないので except は飛ばされるが、finally は必ず動く。

PY10-D08 except: とだけ書いて全てのエラーを拾う書き方が推奨されない理由はどれか。
A. 動作が遅くなる B. 想定外のエラーまで握りつぶし、原因が分からなくなる C. 文法エラーになる D. finallyが動かなくなる
選択★★☆無料
期待される結果

解答 == B

ヒント

バグを見つけやすいコードとはどういうものか。

模範解答
B
解説

典型的な事故は、変数名のタイプミス(NameError)まで握りつぶして「なぜか動かない」状態になること。捕まえるエラーは具体的に指定する

PY10-D09 values = ["10", "abc", "0"] の各要素について 100 ÷ 数値 を計算せよ。数値に変換できなければ「変換エラー」、0で割ろうとしたら「ゼロ除算エラー」、成功したら計算結果を出力すること。 コーディング★★☆無料
期待される結果

出力 == 10.0 / 変換エラー / ゼロ除算エラー(3行)

ヒント

except は複数並べられる。ValueError と ZeroDivisionError の2つを書く。

模範解答
values = ["10", "abc", "0"]

for v in values:
    try:
        print(100 / int(v))
    except ValueError:
        print("変換エラー")
    except ZeroDivisionError:
        print("ゼロ除算エラー")
解説

except を複数並べて種類ごとに対応を変えるのが基本形。1件失敗してもループは止まらず次に進む点が重要。

PY10-D10 d = {"name": "田中"} から "age" を取り出し、キーが無ければ「ageは未登録です」と出力せよ(try/except を使うこと)。 コーディング★★☆無料
期待される結果

出力 == ageは未登録です

ヒント

辞書に無いキーを角カッコで引くと KeyError が出る。

模範解答
d = {"name": "田中"}

try:
    print(d["age"])
except KeyError:
    print("ageは未登録です")
解説

PY07で学んだ get() を使えば例外なしでも書ける。単純な既定値なら get()、処理を分けたいなら try/except と使い分ける。

4実践シナリオ(5問)

PY10-S01 【安全な割り算関数】2つの数を受け取り割り算の結果を返す関数 safe_div を定義せよ。0で割る場合は None を返すこと。(10, 2)、(10, 0)、(7, 3) の3件について、成功時は「10 ÷ 2 = 5.00」(小数2桁)、失敗時は「10 ÷ 0 = 計算できません」の形式で出力せよ。 コーディング★★☆無料
期待される結果

出力3行が完全一致

ヒント

関数の中で try/except し、except では return None。呼び出し側で if result is None: と判定する。

模範解答
def safe_div(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return None


for a, b in [(10, 2), (10, 0), (7, 3)]:
    result = safe_div(a, b)

    if result is None:
        print(f"{a} ÷ {b} = 計算できません")
    else:
        print(f"{a} ÷ {b} = {result:.2f}")
解説

エラーを None に変換して返すのは実務でよく使う設計。呼び出し側は例外を意識せず if で分岐できる。None の比較は == ではなく is None と書くのが作法。

PY10-S02 【不正データを飛ばして集計】raw = ["120", "abc", "85", "", "43"] を整数に変換せよ。変換できないものはスキップし、成功したものだけで集計して3行出力すること。
「変換成功:[120, 85, 43]」「成功3件 / 失敗2件」「合計:248」
コーディング★★☆無料
期待される結果

出力3行が完全一致

ヒント

空のリストと失敗カウンタを用意し、try の中で append、except ValueError: でカウントする。

模範解答
raw = ["120", "abc", "85", "", "43"]

nums = []
failed = 0

for r in raw:
    try:
        nums.append(int(r))
    except ValueError:
        failed += 1

print(f"変換成功:{nums}")
print(f"成功{len(nums)}件 / 失敗{failed}件")
print(f"合計:{sum(nums)}")
解説

PY09の内包表記は途中で失敗すると全体が落ちるので、汚れたデータには使えない。1件ずつ try で守りながら回すのが実務のデータ取り込みの形。

PY10-S03 【設定値の読み込み】config = {"host": "localhost", "port": "8080"} から ["host", "port", "timeout"] を順に取り出して「host = localhost」の形式で出力せよ。キーが無い場合は「timeout = 未設定(既定値30を使用)」と出力すること(既定値は defaults = {"timeout": 30} から取る)。 コーディング★★☆無料
期待される結果

出力3行が完全一致

ヒント

for key in [...] で回し、try の中で config[key] を参照。except KeyError: で既定値の側を出力する。

模範解答
config = {"host": "localhost", "port": "8080"}
defaults = {"timeout": 30}

for key in ["host", "port", "timeout"]:
    try:
        print(f"{key} = {config[key]}")
    except KeyError:
        print(f"{key} = 未設定(既定値{defaults[key]}を使用)")
解説

設定ファイルは項目が欠けていることが日常的にある。欠損しても既定値で動き続ける設計にしておくのが堅牢なプログラム。

PY10-S04 【raise で自作エラー】年齢を受け取り、0未満または150超なら raise ValueError("年齢が不正です") し、正常なら "OK" を返す関数 check_age を定義せよ。[30, -5, 200] の3件を「30 → OK」「-5 → エラー:年齢が不正です」の形式で出力すること。 コーディング★★★無料
期待される結果

出力3行が完全一致

ヒント

関数の中で条件を判定して raise する。呼び出し側で try / except ValueError as e: して e を表示する。

模範解答
def check_age(age):
    if age < 0 or age > 150:
        raise ValueError("年齢が不正です")
    return "OK"


for age in [30, -5, 200]:
    try:
        print(f"{age} → {check_age(age)}")
    except ValueError as e:
        print(f"{age} → エラー:{e}")
解説

不正を見つけた側が raise し、対応を決めるのは呼び出した側——これが例外の設計思想。関数の中で print して握りつぶすと、呼び出し側が失敗に気づけなくなる。

PY10-S05 【finally で後始末】data = ["10", "abc"] の各要素について、処理の開始と終了を必ず記録せよ。
「[10] 処理開始」→ 成功なら「→ 結果:100」(10倍した値)/失敗なら「→ 変換に失敗しました」→「[10] 処理終了」の順に出力し、最後に「完了:2件処理」と出力すること。
コーディング★★★無料
期待される結果

出力7行が完全一致

ヒント

ループの中で開始を print → try/except → finally で終了を print。finally はエラーの有無に関係なく実行される。

模範解答
data = ["10", "abc"]

for d in data:
    print(f"[{d}] 処理開始")

    try:
        print(f"→ 結果:{int(d) * 10}")
    except ValueError:
        print("→ 変換に失敗しました")
    finally:
        print(f"[{d}] 処理終了")

print(f"完了:{len(data)}件処理")
解説

finally があるので失敗した回でも必ず「処理終了」が記録される。実務ではここでファイルを閉じたり接続を切ったりする。書き忘れるとリソースが残り続ける原因になる。

5仕上げ課題

PY10-FINAL 【CSV行データの検証スクリプト】1行ずつ検証し、不正な行はエラー内容を表示して飛ばし、正常な行だけを集計せよ。
rows = [
  "田中,営業,82",
  "鈴木,開発,abc",
  "佐藤,人事",
  "高橋,広報,91",
  ",総務,55"
]


各行は「名前,部署,点数」の形式。検証ルール:
① 項目が3つ未満 → 「項目数が不足しています」
② 名前が空 → 「名前が空です」
③ 点数が数値に変換できない → 「点数が不正です」
いずれも raise ValueError(メッセージ) で通知し、呼び出し側でまとめて受け止めること。

出力仕様(9行):
=== データ検証 ===
1行目:田中(営業)82点
2行目:エラー — 点数が不正です
3行目:エラー — 項目数が不足しています
4行目:高橋(広報)91点
5行目:エラー — 名前が空です
---
成功:2件 / 失敗:3件
平均点:86.5点
期待される結果

出力9行が完全一致

ヒント

行を項目に分けるには row.split(",") を使う(カンマで区切ったリストが返る)。3つの検証を順に行い、問題があれば raise ValueError(...)。点数の変換は内側の try で受け止め、except の中から改めて raise ValueError("点数が不正です") する。エラー行は continue で飛ばす。

模範解答
rows = [
    "田中,営業,82",
    "鈴木,開発,abc",
    "佐藤,人事",
    "高橋,広報,91",
    ",総務,55"
]

print("=== データ検証 ===")

scores = []
errors = 0

for i, row in enumerate(rows, 1):
    parts = row.split(",")

    try:
        if len(parts) < 3:
            raise ValueError("項目数が不足しています")

        name = parts[0].strip()
        if not name:
            raise ValueError("名前が空です")

        try:
            score = int(parts[2])
        except ValueError:
            raise ValueError("点数が不正です")

    except ValueError as e:
        print(f"{i}行目:エラー — {e}")
        errors += 1
        continue

    scores.append(score)
    print(f"{i}行目:{name}({parts[1].strip()}){score}点")

print("---")
print(f"成功:{len(scores)}件 / 失敗:{errors}件")
print(f"平均点:{sum(scores) / len(scores):.1f}点")
解説

検証は raise、対応は except、失敗行は continue で次へ——これが実務のデータ取り込み処理の完成形。1件の不正データで全体が止まらず、しかも何が悪かったかが記録される。5,000行のCSVに1行だけ壊れた行が混ざっていても、このスクリプトなら残り4,999行を処理し切れる。ここまで書ければ「業務で使えるスクリプト」の水準に達している。