csvモジュール
このレッスンでできるようになること。手書きの split をやめて、標準の csv モジュールで家計簿ファイルを読み書きできるようになります。
入門では、カンマ区切りの1行を line.split(",") で分解していました。データが「ノート,200,文具」のように素直なうちは、これで問題ありません。ところが家計簿には「コーヒー, 豆」のように、品名そのものにカンマが入る行がいつか現れます。そのとき split は品名を2つに割ってしまい、金額の位置がずれて集計が壊れます。
この手の面倒は、CSV という形式を作った人たちがとっくに解決しています。値の中にカンマがあるときは、その値をダブルクォートで囲むという決まりです。読む側はクォートの内側のカンマを区切りとして数えません。標準ライブラリの csv モジュールは、この決まりを最初から知っています。
書くときは csv.writer(f) を作り、writerow で1行、writerows でまとめて書きます。クォートが必要な値には、csv 側が勝手に付けてくれます。読むときは csv.reader(f) を作り、for で回すと1行が文字列のリストになって返ってきます。
import csv
with open("shishutsu.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(["品名", "金額"])
writer.writerow(["コーヒー, 豆", 980])
with open("shishutsu.csv", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
print(row)注意することが2つあります。1つ目は、書くときの open に newline="" を付けることです。付けないと環境によっては空行が1行おきに混ざります。2つ目は、encoding="utf-8" を必ず書くことです。日本語のデータを扱うので、ここを省くと後で文字化けします。
もう1つ覚えておきたいのが next(reader) です。1行目の見出し行を1回だけ取り出して、残りをデータとして回すときに使います。csv.reader が返す値はすべて文字列なので、金額を足すときは int(row[1]) のように数値へ戻す必要があります。
要件
- csv.writer で見出し行を含む rows をすべて kakeibo_csv.csv に書き出す
- 書き出しの open には encoding="utf-8" と newline="" を付ける
- csv.reader で読み直し、next で見出し行を読み飛ばす
- データ行ごとに「品名 金額」を空白区切りで表示する
- 最後に「合計 13180」の形で合計金額を表示する
入出力例
出力: "ノート 200
コーヒー, 豆 980
定期券 12000
合計 13180
"