CHAPTER 9 ・ AIと一緒に、中級者として / Lesson 36

AIが書いたコードを点検する(中級)

エラーの握りつぶし、決め打ちの値、遅い書き方、危ない操作。中級者の目でチェックする観点です。

目安 25分 ・ インストール不要

このレッスンが終わったら

「AIのコードは、握りつぶし・決め打ち・上書き削除・外部送信の4点で点検する。分からない部分は、AIに説明させてから採用する」と言える。

STEP 1

こんな場面、ありませんか?

AIが書いたコードを実行したら、エラーも出ず、数字がきれいに表示された。基礎編では、そんなときこそ「読む」「検算する」と学びました。中級になると、コードが長くなり、動いているのに、間違っている(あるいは危ない)コードに出会う場面が増えます。

次は、AIが書いた、売上CSVの合計を出すコードです。messy.csv は、表記ゆれや欠損が混ざった10行のデータです。

AIが書いた、売上合計のコードサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

エラーはなく、「96000」と表示されました。ところが、messy.csv をExcelで開くと、金額の入った行が8行あり、足すと50万円を超えます。表示された合計は、5分の1以下です。何が起きたのでしょうか。

STEP 2

点検の観点を、順番に当てる

「読む」だけでなく、決まった観点で、1つずつ当てていくと、見落としが減ります。これが、AIのコードを点検(コードレビュー)するということです。

観点見つけるサイン起きること
① エラーの握りつぶしexcept: のあとが pass、except Exception で空のデータにする間違いに気づけない
② 決め打ちパス、日付、列名、税率などが、コードに直接書かれている他のPC・他の月で壊れる
③ 上書き・削除open(..., "w") で元のファイルを開く、os.remove元のデータが失われる
④ 外部への送信・秘密情報requests.post、API_KEY = "..."情報が漏れる
⑤ 遅い・重い書き方ループの中でファイルを何度も開く件数が増えると終わらない
⑥ テストがない確かめる手段がない直したときに壊れても分からない

先ほどのコードは、①に当たります。except: で全部のエラーを受け止め、pass で何もしないため、変換できなかった行が黙って捨てられています。この握りつぶしを外して、何が起きているのか、見える形にします。

捨てられた行を、表示してみるサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

8行が捨てられていました。原因の多くは、'120,000' のような桁区切りのカンマで、int() が変換できなかったためです。一方、''(空欄)と '不明' は、本当に変換できない行です。捨てるなら、何件捨てたかを必ず見えるようにする。これが、握りつぶしを避ける基本です(Lesson 09)。

STEP 3

怪しいコードを、読む

実際のAIのコードは、1本に複数の問題が混ざっています。次のコードから、②③④の問題点を探してみてください(動かさずに、読むだけです)。

import csv
import os
import requests

API_KEY = "sk-abc123-secret"
path = "C:\\Users\\tanaka\\Desktop\\expenses.csv"
with open(path, encoding="utf-8") as f:
    rows = list(csv.DictReader(f))
total = sum(int(r["金額"]) * 1.1 for r in rows)
requests.post("https://example.com/upload", json={"total": total}, headers={"Authorization": API_KEY})
os.remove(path)  # 後片付け
問題点を、観点ごとに日本語にする
API_KEY = "sk-abc123-secret"④ 秘密のキーが、コードに丸見え(環境変数に置く。Lesson 32)
path = "C:\\Users\\tanaka\\..."② 田中さんのパソコンにしかない場所の、決め打ち
int(r[...]) * 1.1② 税率の決め打ち。8%の商品も、10%で計算される
requests.post(...)④ 合計額を、外部のURLに送信している。送り先と中身を確認
os.remove(path)③ 元のファイルを、削除している

どの行も、1行ずつ見れば、もっともらしく見えます。観点を決めて見るから、気づけるのです。AIに点検を手伝ってもらうときは、次のように頼みます。

AIに、点検を頼むときの文章

次のPythonコードを、点検してください。問題点を、重要度の高い順に、箇条書きで挙げてください。

【見てほしい観点】
1. エラーを握りつぶしていないか(except: pass など)
2. パス・日付・列名・税率などを、決め打ちしていないか
3. 元のファイルを上書き・削除していないか
4. データを外部に送信していないか。キーやパスワードがコードに書かれていないか
5. 遅い・メモリを多く使う書き方はないか

【お願い】
- 各指摘に、該当する行と、直し方を添える。問題がない観点は「問題なし」と書く
- 分からない行があれば、初心者向けに説明する

【コード】
(ここにコードを貼る)

ただし、AIの指摘も鵜呑みにしません。間違った指摘や、大げさな指摘が混ざることがあるからです。たとえば、「ファイルを close() していません」と言われたとき、コードが with open(...) を使っているなら、本当でしょうか。

AIの指摘を、自分で確かめるサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

True、つまり閉じています。with が、自動で閉じてくれるためです。指摘は、自分で確かめてから、採用する。分からない部分は、AIに説明させてから、採用しましょう。

STEP 4

変えて、試す

観点②(決め打ち)、③(上書き)、⑤(遅い)を、動かして確かめます。まず、②の税率です。

②:税率を10%に決め打ちした集計サンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

9月には、8%の商品(ミネラルウォーター)の伝票が2枚あり、10%で計算されています。小さな差でも、請求の金額が合わなくなる原因です。

次は、③の上書きです。「空欄のある行を取り除く」というコードです。

③:元のファイルに、上書き保存するサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

8行あったデータが、5行になりました。取り除いた3行は、ファイルから消えました。どの行に問題があったのか、あとから確認することもできません。保存先は、必ず別の名前にします(Lesson 29)。

最後に、⑤の遅い書き方です。売上の1行ごとに、products.csv を開き直すコードを、開いた回数で比べます。

⑤:ループの中で、ファイルを何度も開くサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

明細128行で、128回開いていました。128行なら一瞬ですが、数万行になると、極端に遅くなります。最初に1回だけ読んで辞書にしておく書き方(Lesson 06)が定番です。

STEP 5

自分で書く

お題① 最初のコード(握りつぶし)を直します。桁区切りのカンマを取り除いて変換し、それでも変換できない行は、件数を数えて表示してください。

お題①:握りつぶしを、直すサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

int(row["金額"].replace(",", "")) でカンマを取ります。except は ValueError にして、中で skipped += 1 と数え、最後に print(f"スキップ: {skipped}件") と表示します。skipped = 0 を、最初に作るのを忘れずに。

答えの例を見る
import csv

total = 0
skipped = 0
with open("messy.csv", encoding="utf-8") as f:
  for row in csv.DictReader(f):
      try:
          total += int(row["金額"].replace(",", ""))
      except ValueError:
          skipped += 1

print("売上合計:", total)
print(f"スキップ: {skipped}件")

お題② 税率の決め打ちを直します。rate_of(商品コード→税率)を使って、商品ごとの税率で、税込金額を計算してください(1円未満は切り捨て)。

お題②:商品ごとの税率で計算するサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

110 のところを、その行の商品の税率にします。(100 + rate_of[r["商品コード"]]) の形です。割り算は // のままです。

答えの例を見る
import csv

with open("products.csv", encoding="utf-8") as f:
  rate_of = {r["商品コード"]: int(r["税率"]) for r in csv.DictReader(f)}

with open("sales_detail.csv", encoding="utf-8") as f:
  rows = [r for r in csv.DictReader(f) if r["日付"][:7] == "2025-09"]

total = sum(int(r["数量"]) * int(r["単価"]) * (100 + rate_of[r["商品コード"]]) // 100 for r in rows)
print(total)
STEP 6

仕事ならどう使う?

理解チェックAIのコードに、except Exception: rows = [] がありました。何が問題でしょう?

理解チェックAIに点検を頼んだら、『ファイルを close() していません』と指摘されました。コードは with open(...) を使っています。どうしますか?