CHAPTER 5 ・ ファイルとテキストの実践 / Lesson 19

CSV と JSON を実務の形で扱う

文字コード・BOM・区切り文字の違いを乗り越える。読み込みから書き出しまで、壊れにくい書き方です。

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

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

「CSVは文字コードと区切りを確認して読む。JSONは ensure_ascii=False と indent を付けて書くと、人が読める」と言える。

STEP 1

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

銀行のシステムや、古い販売管理ソフトから出力したCSVを、基礎編の書き方で読んだら、いきなりエラーで止まった。そんな経験は、実務でよくあります。原因は、ファイルの中身(文字)の書き方の約束が、思っていたものと違うことです。

この講座の画面では、銀行のCSVの代わりに、コードの中で同じ形式のファイルを作ります(encoding="cp932" で書き出します)。それを、基礎編と同じ書き方で読んでみましょう。

基礎編の書き方で読む:エラーになるコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

UnicodeDecodeError(この文字コードでは読めません)と出ます。ファイルの書き方(文字コード)と、読むときの指定が、食い違っているのです。

STEP 2

文字コードを合わせて読む

日本の実務で出会う文字コードは、おもに次の3つです。

指定する名前どこで出会うか見分けるヒント
utf-8最近のシステム、Web、Python の標準基礎編の書き方で読める
utf-8-sigExcel の「CSV UTF-8」で保存したもの読むと、1つ目の見出しの前に目に見えない文字が付く
cp932銀行、古い会計・販売管理ソフト、Windows 版 Excel の「CSV」utf-8 で読むと UnicodeDecodeError

cp932(シフトJISの仲間)のファイルは、encoding="cp932" と指定すれば読めます。

cp932 を指定して読むコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

もう1つの落とし穴です。Excel が作る UTF-8 のCSVには、先頭にBOMという目印が付くことがあります。utf-8 のまま読むと、見出しの文字が変わってしまいます。

BOM 付きのファイルを、utf-8 と utf-8-sig で読み比べるコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

1つ目の見出しが '\ufeff得意先名' になっています。目に見えない BOM が見出しの一部になり、row["得意先名"] と書くと KeyError になります。utf-8-sig なら、BOM が取り除かれます。

STEP 3

書き出しの仕組みを読む

読むときと同じく、書き出すときも文字コードを指定します。open の部品を分けてみます。

open("summary.csv", "w", encoding="utf-8-sig", newline="") の部品
"summary.csv"ファイルの名前
"w"書き込みモード
encoding="utf-8-sig"文字コード(Excelで開いても化けない)
newline=""改行の自動変換を止める(csv モジュールの決まり)

そして、辞書のリストをCSVに書き出す csv.DictWriter は、次の3ステップです。

DictWriter を、1行ずつ日本語にしてみる
with open(...) as f:書き込み用にファイルを開く
w = csv.DictWriter(f, fieldnames=["部署", "売上"])「部署」「売上」の列で書く係を用意する
w.writeheader()1行目に、見出しを書く
w.writerows(rows)辞書のリスト rows を、1行ずつ書く

日本語にすると、「summary.csv を Excel でも化けない文字コードで開き、見出しを書いてから、rows を1行ずつ書く」です。

newline="" は、Windows で行と行のあいだに空行が入るのを防ぐ指定です。意味を覚えなくてよいので、CSVを書くときは必ず付けると決めてしまいましょう。

STEP 4

変えて、試す

① 集計結果をCSVに書き出す。 sales.csv を部署ごとに合計して、summary.csv に書きます。書いたあとで読み直し、中身を確かめます。

部署別の合計を、summary.csv に書き出すサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

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

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

② 値にカンマやダブルクォートが入るとき。 摘要に「文具, 事務用品」のようにカンマが入ると、そのまま書くと列がずれてしまいます。csv は、そういう値を自動でダブルクォートで囲みます。また、区切りがカンマでなくタブ(\t)のファイルは、delimiter で区切り文字を伝えます。

カンマを含む値と、タブ区切りコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

囲まれた値は、読み込むときに元のカンマ入りの値に戻ります。読む側にも delimiter="\t" を渡している点に注意してください。

③ JSON を、人が読める形で書く。 JSONは、json.dumps で文字にできます。日本語の部分が 会 のような記号になるのを、ensure_ascii=False で防ぎ、indent=2 で字下げして読みやすくします。

ensure_ascii と indent の有無を比べるコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

1行目の \u4f1a のような書き方はエスケープと呼ばれ、コンピュータには正しく伝わりますが、人には読めません。日付(date)をそのまま入れると、JSON にできずエラーになります。

わざと間違える:日付をそのまま JSON にしたコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

TypeError(日付は JSON にできません)と出ます。default=str を付けると、JSON にできない値を、文字にして書きます("2025-09-30" になります)。

④ 設定ファイルとして使う。 税率やフォルダ名のように、変わりやすい値をコードの外に出すときも JSON が便利です。書いて、読み直します。

config.json に書いて、読み直すコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

dumps / loads は「文字との変換」、dump / load は「ファイルとの読み書き」です(s は string の s)。

STEP 5

自分で書く

お題① 部署ごとの合計 totals を summary.csv に書き出し(Excel で開いても化けない文字コードで)、書いたファイルを読み直して表示してください。

お題①:集計結果を DictWriter で書くコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

rows = [{"部署": k, "売上": v} for k, v in totals.items()] で作ります。書くときは encoding="utf-8-sig", newline=""。読み直すときも encoding="utf-8-sig" にしないと、先頭に BOM が付いて見えます。

答えの例を見る
import csv

totals = {"営業": 1110000, "企画": 540000}

rows = [{"部署": k, "売上": v} for k, v in totals.items()]
with open("summary.csv", "w", encoding="utf-8-sig", newline="") as f:
  w = csv.DictWriter(f, fieldnames=["部署", "売上"])
  w.writeheader()
  w.writerows(rows)

print(open("summary.csv", encoding="utf-8-sig").read())

お題② 辞書 data を、日本語がそのまま読める形で、字下げ2つで表示してください。

お題②:JSON の整形出力コードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

json.dumps(data, ensure_ascii=False, indent=2) を print します。

答えの例を見る
import json

data = {"会社": "サクラ商事", "部署": ["営業", "企画"]}

print(json.dumps(data, ensure_ascii=False, indent=2))

お題③ cp932 で作られた bank.csv を読み、入金額の合計を表示してください。ファイルを作る部分は、最初から書いてあります。

お題③:cp932 のCSVを読んで合計するコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

open("bank.csv", encoding="cp932") で開き、csv.DictReader で読みます。入金額は文字なので int() に直してから足します。

答えの例を見る
import csv

with open("bank.csv", "w", encoding="cp932", newline="") as f:
  f.write("得意先名,入金額\nアオイ電機,1320000\nミドリ商事,484000\nサクラ印刷,792000\n")

with open("bank.csv", encoding="cp932") as f:
  total = sum(int(row["入金額"]) for row in csv.DictReader(f))
print(total)
STEP 6

仕事ならどう使う?

理解チェック集計結果を CSV に書いて、Excel でそのまま開いても文字化けしないようにしたい。open の encoding は、どれがよいでしょう?

理解チェックjson.dumps で書いた結果の日本語が、\u4f1a のような記号になってしまいました。直すには?