json と csv — 構造化データの入出力
json.dumps/loadsの相互変換とensure_ascii、csv.writer/readerの位置ベース、DictWriter/DictReaderの列名ベースをTitanicデータ集計まで実例で学べます。
構造化データの代表的な形式 2 つ — Web API でよく使うjsonと、表計算ソフトで開けるcsv — の入出力を整理します。
JSON と CSV — どんなときに使う?JSONはキーと値・入れ子構造を表現できるので Web API のレスポンスや設定ファイルで頻出。CSVは1 行 = 1 レコードの表形式で、Excel などの表計算ソフトで開けるためデータ分析で頻出。json — Python オブジェクトと JSON 文字列の相互変換
JSON(JavaScript Object Notation)は「キーと値の対応」と「並びのリスト」だけで構造を表現する軽量なテキスト形式で、Web API のレスポンスや設定ファイルで標準的に使われます。Python ではjson モジュールが辞書・リスト・文字列・数値・bool・Noneを JSON との間で相互変換してくれます。
2 つの基本関数を覚えれば十分です。json.dumps(オブジェクト)でPython → JSON 文字列、json.loads(文字列)でJSON 文字列 → Python。語尾のsはstringの意味で、ファイルを直接読み書きするdump / loadと区別されています。
json.dumps と json.loads の対称性上段はdumps(dump string)= Python → JSON 文字列へ書き出す方向。下段はloads(load string)= JSON 文字列 → Pythonへ読み込む方向。s抜きのdump / loadはファイルオブジェクトを直接扱うバージョン。| 関数 | 役割 | 備考 |
|---|
| json.dumps(obj) | Python → JSON 文字列 | 戻り値は str |
| json.loads(text) | JSON 文字列 → Python | 戻り値は dict / list など |
| json.dump(obj, file) | Python → ファイルに書き出し | open() の f を渡す |
| json.load(file) | ファイル → Python | open() の f を渡す |
| indent=N | 整形して N スペース字下げ | 人間に読ませるとき |
| ensure_ascii=False | 日本語などの非 ASCII をそのまま出力 | 既定はエスケープされる |

ensure_ascii の既定は True
json.dumps({"name": "太郎"})の既定の出力は'{"name": "\u592a\u90ce"}'のように日本語が \u エスケープされます。これは仕様としては正しいのですが、人間が読みづらく、ファイルサイズも増えるので、日本語データには ensure_ascii=False を必ず付けるのが定石です。

ユーザー情報を JSON に変換し、再度 Python オブジェクトに戻して、各変数の型もtype()で確認します。
① json モジュールを読み込んでください
② name="Alice"と商品リスト["Apple", "Banana"]を持つ辞書を用意してください(nameキーとitemsキーの 2 項目)
③ その辞書を整形済み(インデント付き)の JSON 文字列に変換して表示し、続けてtype(text):の形でJSON 文字列の型を表示してください(日本語の場合に備えて非 ASCII エスケープを無効化します)
④ その JSON 文字列を再度 Python オブジェクトに戻し、続けてtype(parsed):とtype(items):の形でそれぞれの型を表示してください(itemsは parsed から取り出します)
⑤ 戻したオブジェクトからname: ◯◯と最初の商品: ◯◯(items の最初の要素)の形で表示してください
(正しく実行できれば解説が表示されます)
csv の基本 — reader と writer で行を扱う
CSV(Comma-Separated Values)は「カンマ区切りの 1 行 = 1 レコード」という素朴な形式で、Excel などの表計算ソフトで開けるため業務でよく使います。Python のcsv モジュールはこの形式の読み書きを行単位で扱うための関数を提供しています。
基本形はcsv.writer(ファイル)とcsv.reader(ファイル)で、それぞれ値のリストを 1 行として書き出す / CSV を 1 行ずつ値のリストとして読み出す動きをします。注意点が 2 つあります — まず読み戻したときの値はすべて文字列になるので、整数として使いたいなら自分でint()変換が必要です。次にopen(...) には必ず newline='' を付けること(改行文字の扱いを csv モジュールに任せるため)。
csv.writer と csv.reader の役割writer.writerow(リスト)で値のリストを CSV の 1 行として書き出す。readerは逆にCSV の 1 行を値のリストとして取り出す — このときすべての値は文字列になる点に注意。
open には newline='' を必ず付ける
csv モジュールは改行文字を独自に管理するため、open("x.csv", "w", newline='')のようにnewline='' を渡す必要があります。これを付けないと、Windows 環境などで空行が混ざった CSVが作られてしまうことがあります — Python 公式ドキュメントでも明示されている定番の落とし穴です。

ユーザーの一覧を CSV に書き出し、再度読み戻して 1 行ずつ表示します。VFS 上のoutput.csvというファイルに対して書き込み・読み込みを行います。
① csv モジュールを読み込んでください
② output.csvを書き込みモード(newline='' 付き)で開いて writer を作り、ヘッダ行["name", "age"]と、データ行["Alice", 30]、["Bob", 25]の計 3 行を書き込んでください
③ 同じファイルを読み込みモード(newline='' 付き)で開き直して reader を作り、for row in reader:で 1 行ずつ取り出して表示してください
DictWriter と DictReader — 列名ベースで読み書きする
前セクションのcsv.writer / readerは「位置」で列を扱うので、列の追加や順序変更があるとコード側のrow[0] / row[1]を全部書き直す必要があります。DictWriter / DictReaderは列名(ヘッダ)で値を出し入れするバージョンで、辞書のリストをそのまま CSV に書き出したり、辞書のリストとして読み戻したりできます。
業務データは大抵「ヘッダ付きの CSV」なので、実プロジェクトではこちらを使うほうが圧倒的に多いです。
DictWriter / DictReader の便利さDictWriterは辞書のリストをfieldnamesで指定したヘッダ付き CSV に変換する。DictReaderは逆にヘッダ付き CSVを辞書のリストとして読み出すので、row["name"]のように列名で値にアクセスできる。
ユーザーの辞書のリストを users.csv に書き出し、再度読み戻して整形表示します。位置ではなく列名でアクセスする書き方を試します。
① csv を読み込んでください
② 2 件のユーザー(name / age / cityの 3 列)を辞書のリストで用意してください
- 1 件目: name="Alice", age=30, city="Tokyo"
- 2 件目: name="Bob", age=25, city="Osaka"
③ users.csvを書き込みモードで開いて DictWriter を作り、ヘッダ行 + データ行を書き込んでください(fieldnamesには["name", "age", "city"]を指定)
④ 同じファイルを開き直して DictReader を作り、各行を{name} ({age}歳) {city}の形で表示してください
実例: titanic.csv を読み込んで集計する
ここまでは小さなデータをコード内で作って書き出していました。最後に本物のデータセットを読み込んで集計する流れを試します。題材はKaggle で有名な Titanic データセット(891 行 / 12 列)で、PassengerId / Survived(0=死亡, 1=生存)/ Pclass(客室等級)/ Name / Sex / Age / Fareなどの列を持ちます。
演習のpython_consoleではfileUrlsで外部 CSV を仮想ファイルシステム(VFS)にプリロードしているので、コード側は普通にopen("titanic.csv")で開けます。csv.reader(位置ベース)とcsv.DictReader(列名ベース)の両方を、同じデータに対して書き比べます。

位置ベースの csv.readerで titanic.csv を読み、乗客の総数と生存者数を集計します。
① csv モジュールを読み込んでください
② titanic.csvを読み込みモード(newline='' 付き)で開いて reader を作ってください
③ ヘッダ行をnext(reader)で読み飛ばしてください
④ 残りの行をfor row in reader:でループし、総人数と生存者数(Survived列 = インデックス 1 が"1"の行)をカウントしてください
⑤ 総人数: 891と生存者: 342の形でそれぞれ表示してください

列名ベースの csv.DictReaderで titanic.csv を読み、Age 列の平均値を計算します。Titanic データにはAge が空欄の行が混じるので、その扱いも合わせて練習します。
① csv を読み込んでください
② titanic.csvを読み込みモード(newline='' 付き)で開いて DictReader を作ってください
③ ループで各行からrow["Age"]を取り出し、空文字でない行だけ float(row["Age"])でリストに集めてください
④ 有効な行数と平均年齢(小数点 2 桁)をそれぞれ次の形で表示してください
- 有効データ件数: ◯(expected: 714)
- 平均年齢: ◯◯.◯◯歳 (expected: 29.70)
Q1json.dumps({"name": "太郎"}, ensure_ascii=False)の出力に含まれるのはどれですか?
Q2csv.readerで読み戻した行の値の型はどれですか?
Q3ヘッダ付き CSV を辞書のリストとして読み込むのに最も向いているのはどれですか?