CHAPTER 3 ・ エラーに強いコード / Lesson 09
エラーが出ても止まらない(try / except)
1行だけおかしなデータがあっても、全体は最後まで処理する。エラーを「受け止めて」進める書き方です。
このレッスンが終わったら
「try の中でエラーが出たら except に移る。起きそうなエラーの種類を指定して、握りつぶさずに記録する」と言える。
こんな場面、ありませんか?
取引先から届いたCSVの「金額」の列に、不明 という文字や、空欄が混ざっていることがあります。サンプルの messy.csv が、その状態です。
日付,得意先名,商品,数量,金額 2025/10/01,アオイ電機(株),ノートPC,1,"120,000" 2025/10/02,株式会社 ミドリ商事,モニター,2,"70,000" 2025-10-03,ミドリ商事株式会社,モニター,2,"70,000" 2025/10/04,サクラ印刷,業務ソフト,1,48000 2025/10/05, サクラ印刷 ,業務ソフト,,48000 2025/10/06,タチバナ工業,保守サービス,1, 2025/10/07,アオイ電機(株),ノートPC,1,"120,000" 2025/10/08,ヒマワリ食品,ミネラルウォーター,10,"15,000" 2025/10/08,ヒマワリ食品,ミネラルウォーター,10,"15,000" 2025/10/09,スミレ運輸,モニター,1,不明
この金額を合計するコードを、基礎編の書き方で書きます。"120,000" のようにカンマ付きの金額があるので、replace でカンマを取り除いてから int() で数字にします(Lesson 02 で学ぶ書き方です)。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
6件目の「タチバナ工業」は金額が空欄で、int("") が変換できず、ValueError(値が正しくない)というエラーになりました。残りの4件は読まれないまま、プログラム全体が止まり、「合計」も表示されません。
1行の不備で全体が止まるのは、件数が多いほど困ります。この回は、try / exceptという書き方で、「エラーが出ても、受け止めて先へ進む」方法を学びます。
try / except で受け止める
まず、いちばん小さな形です。数字にできない "abc" を、わざと int() に渡します。
▶ 実行を押すと、ここに結果が出ます
赤いエラーは出ず、最後の行まで進みました。print("変換できました") は、その前の int("abc") で止まったので、実行されていません。as e と書くと、エラーの説明文を e として取り出せます。
では、messy.csv の合計を、読めない行だけ飛ばして最後まで計算します。飛ばした行は、あとで確認できるように記録します。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
合計が出て、どの行が読めなかったかも画面に残っています。「飛ばす」と「記録する」は、必ずセットにします。
仕組みを読む
try 文は、最大で4つのブロックでできています。使うのは try と except だけのことが多く、残りは必要なときに足します。
- tryためしに実行する
- exceptエラーが出たときだけ
- elseエラーが出なかったときだけ
- finallyどちらでも、最後に必ず
さきほどのコードの中心部分を、1行ずつ日本語にします。enumerate は、Lesson 05 で学んだ、番号を付けて取り出す書き方です。
for line_no, row in enumerate(rows, start=2):行を1つずつ取り出す(番号は、見出しの次の2行目から) try:ためしに、次の行を実行してみる amount = int(row["金額"].replace(",", ""))金額のカンマを取って、整数にする except ValueError:もし ValueError(変換できない)が出たら、ここへ移る skipped.append((line_no, row["金額"]))何行目の、どんな値だったかを、記録する continueこの行はここで終わり。次の行へ進む日本語にすると
変えて、試す
① エラーの種類で、対応を分ける。 except は何個でも並べられます。「0で割った」と「数字ではない値が入っていた」で、メッセージを変えます。
▶ 実行を押すと、ここに結果が出ます
ZeroDivisionError は0で割ったとき、TypeError は文字と数字を計算しようとしたときのエラーです。書いていない種類(たとえば列名の打ち間違いによる KeyError)は受け止められず、そのまま止まります。これは良いことです。受け止めるのは、起きると分かっているエラーだけにします。
② else と finally。 ファイルを読む関数で、「読めたとき」「読めなかったとき」「どちらでも最後に」を書き分けます。FileNotFoundError は、ファイルが見つからないときのエラーです。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
finally は、エラーが出ても出なくても実行されます。一時ファイルを消すなど、「後片付け」に使います。
③ 握りつぶすと、どうなるか。 except Exception は「どんな種類のエラーでも受け止める」書き方です。便利ですが、except の中を pass(何もしない)にして、エラーを無視してみます。わざと、列名を打ち間違えます(「額」を「客」にしています)。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
エラーは一度も出ず、「合計: 0」と表示されました。10件すべてが失敗しているのに、誰にも知らされません。 この 0 をそのまま報告書に使えば、間違いに気づけません。
「代わりの値」には、None(値がないことを表す特別な値)がよく使われます。None かどうかは、x is None で調べます。
自分で書く
お題① カンマを取り除いて整数にして返し、変換できないときは None を返す関数 safe_int を書いてください。
▶ 実行を押すと、ここに結果が出ます
ヒントを見る
def safe_int(text): の中に、try: return int(text.replace(",", "")) と書き、except ValueError: return None と続けます。
答えの例を見る
def safe_int(text):
try:
return int(text.replace(",", ""))
except ValueError:
return None
print(safe_int("1,200"))
print(safe_int("不明"))
print(safe_int(""))お題② messy.csv の金額のうち、読めない行が何行あるかを数えて、表示してください。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
ヒントを見る
count = 0 から始めます。for で回して、try の中で int(row["金額"].replace(",", "")) を実行し、except ValueError: のときに count に1を足します。
答えの例を見る
import csv
with open("messy.csv", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
count = 0
for row in rows:
try:
int(row["金額"].replace(",", ""))
except ValueError:
count += 1
print(count)お題③ ファイル名を受け取り、あれば「n行」、なければ「ファイル名 がありません」と表示する count_lines を完成させてください。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
ヒントを見る
try の中で with open(path, encoding="utf-8") as f: lines = f.readlines() とします。except FileNotFoundError: で「がありません」を表示し、else: で行数を表示します。
答えの例を見る
def count_lines(path):
try:
with open(path, encoding="utf-8") as f:
lines = f.readlines()
except FileNotFoundError:
print(path, "がありません")
else:
print(f"{len(lines)}行")
count_lines("sales.csv")
count_lines("sales_2026.csv")仕事ならどう使う?
理解チェックtry の中で int("abc") を実行した直後に print("A") があり、except ValueError の中に print("B")、try 文のあとに print("C") がある。何が表示される?
理解チェックexcept の中を pass だけにして、エラーを無視する書き方の、いちばん大きな問題はどれでしょう?