Python講座 / CSVファイルを読み書きする
CSVは行と項目をテキストで保存する形式です。区切り文字や引用符はcsvモジュールで扱い、DictReaderが通常は文字列を返す数値項目は、検証してから型を変換します。
コンマで分割するだけでは不十分な理由
引用符で囲んだ項目は、コンマや改行を含められます。split(",")ではその規則を解釈できません。DictReaderは見出し行を使って項目を対応付けますが、重複見出しや項目数の不一致の扱いは、アプリ側の規則として決める必要があります。
CSVはnewline=""で開き、csvモジュールへ改行処理を任せます。utf-8-sigによる読み取りならUTF-8のBOMを受け入れられ、ツールによっては最初の見出しの一部として現れるBOMの問題を避けられます。
コンマを含む名前を保存して合計する
専用の実習フォルダーでcsv_demo.pyを保存し、仮想環境でpython csv_demo.pyを実行します。expenses-demo.csvを置き換えるので、同名の大切なファイルがない場所を使います。
import csv
from pathlib import Path
path = Path("expenses-demo.csv")
with path.open("w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["name", "amount"])
writer.writeheader()
writer.writerows([{ "name": "lunch, team", "amount": 8000}, {"name": "bus", "amount": 2500}])
total = 0
with path.open(encoding="utf-8-sig", newline="") as f:
reader = csv.DictReader(f)
if reader.fieldnames != ["name", "amount"]:
raise ValueError("unexpected header")
for row in reader:
total += int(row["amount"])
print(row["name"])
print("total:", total)
予想結果です。lunch, teamが一つの名前として読み取られます。
lunch, team bus total: 10500
数値とレコードの検証規則を決める
空の金額、3桁区切り、通貨の接尾辞は、すべてそのままint()へ渡せるわけではありません。どの形式を受け付け、どの行をどう報告するかを先に定めます。無制限に文字を取り除くと、不正な値を正しいように見せることがあります。
enumerate(reader, start=2)は見出しの次から論理レコードへ番号を付ける方法です。引用符内に改行があると、物理的なファイル行番号とは一致しません。エラーがどの種類の位置を指すのかも明確にします。
再実行と表計算ソフトへの出力を確認する
CSV自体は項目の型や、表計算ソフトが式として解釈する規則を保証しません。外部入力が=で始まると式として扱うアプリもあるため、受け取り先に合った検証と文字列としての処理が必要です。引用符で囲むだけで、式の解釈まで決まるわけではありません。
元のCSVを開いて二列であることを確認します。amountの見出しをcostへ替え、検証で止まることを試したら戻します。wモードの再実行では行を追加し続けず、例を置き換えます。不正レコードも報告する取り込み全体はCSV検証の総合実習で扱います。
"coffee, large" はCSVでは一つのフィールドです。csv.readerは一つの文字列として復元しますが、単純なsplitは二つに分けます。保存したテキストの引用符を確認し、csv.readerで読み直してフィールド数と値が一致するか確認します。カンマが見えるだけで列が増えたとは判断できません。




