Python csv.DictWriter()とは?辞書をCSVに書き込む方法

Pythonのcsv.DictWriter()は、辞書をCSVファイルの1行として書き出すクラスです。

APIやデータベースから受け取ったデータは辞書のリストであることが多く、そのままCSVにできます。


csv.DictWriter()の基本的な使い方

import csv

rows = [
    {"name": "佐藤", "age": 28, "city": "東京"},
    {"name": "鈴木", "age": 34, "city": "大阪"},
]

with open("out.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "age", "city"])
    writer.writeheader()
    writer.writerows(rows)

できあがったout.csv:

name,age,city
佐藤,28,東京
鈴木,34,大阪

手順は3つです。fieldnamesを決める → writeheader() → writerow()/writerows()。

メソッド 役割
writeheader() fieldnamesを列名の行として書く
writerow() 辞書を1つ書く
writerows() 辞書のリストをまとめて書く

fieldnamesは必須

csv.writer()と違い、列名の指定を省略できません。

import csv

csv.DictWriter(open("x.csv", "w", newline=""))

実行結果:

TypeError: __init__() missing 1 required positional argument: 'fieldnames'

辞書には決まった順番がないため、どの列をどの順で書くかを決めるのはfieldnamesの役目です。データ側のキーの順番は結果に影響しません。

import csv

with open("o.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=["name", "age"])
    w.writeheader()
    w.writerow({"age": 28, "name": "佐藤"})

print(open("o.csv", newline="", encoding="utf-8").read())

実行結果:

name,age
佐藤,28

writeheader()を忘れるとどうなるか

import csv

rows = [{"name": "佐藤", "age": 28, "city": "東京"},
        {"name": "鈴木", "age": 34, "city": "大阪"}]

with open("nohead.csv", "w", newline="", encoding="utf-8") as f:
    csv.DictWriter(f, fieldnames=["name", "age", "city"]).writerows(rows)

print(open("nohead.csv", newline="", encoding="utf-8").read())

実行結果:

佐藤,28,東京
鈴木,34,大阪

エラーにはならず、列名の行だけがないCSVができます。受け取った側は何の列か分からないため、忘れやすく影響も大きいミスです。


列を絞る・並べ替える

fieldnamesに書いた列だけが、書いた順で出力されます。

import csv

rows = [{"name": "佐藤", "age": 28, "city": "東京"},
        {"name": "鈴木", "age": 34, "city": "大阪"}]

with open("sel.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=["city", "name"], extrasaction="ignore")
    w.writeheader()
    w.writerows(rows)

print(open("sel.csv", newline="", encoding="utf-8").read())

実行結果:

city,name
東京,佐藤
大阪,鈴木

ageは出力されず、順番もcityが先になりました。個人情報を含む列を落として共有する、といった使い方ができます。


fieldnamesにないキーがあるとエラー

上の例でextrasaction="ignore"を付けたのはこのためです。既定では例外になります。

import csv

with open("e.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=["name", "age"])
    w.writeheader()
    w.writerow({"name": "佐藤", "age": 28, "city": "東京"})

実行結果:

ValueError: dict contains fields not in fieldnames: 'city'
extrasaction 余分なキーがあったとき
"raise"(既定) ValueErrorを出す
"ignore" 黙って捨てる

既定が"raise"なのは親切な設計です。書いたつもりの列が消えている事故を防いでくれます。意図して捨てるときだけ"ignore"にしてください。


キーが足りないとき|restval

逆に、辞書にキーがない場合はエラーになりません。

import csv

with open("r.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=["name", "age", "city"])
    w.writeheader()
    w.writerow({"name": "高橋"})

print(repr(open("r.csv", newline="", encoding="utf-8").read()))

実行結果:

'name,age,city\r\n高橋,,\r\n'

空欄になります。別の値を入れたいときはrestvalを指定します。

import csv

with open("r2.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=["name", "age", "city"], restval="不明")
    w.writeheader()
    w.writerow({"name": "高橋"})

print(repr(open("r2.csv", newline="", encoding="utf-8").read()))

実行結果:

'name,age,city\r\n高橋,不明,不明\r\n'

既存のCSVに追記する

モードを"a"にして、writeheader()は呼ばないのがポイントです。

import csv

with open("out.csv", "a", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=["name", "age", "city"])
    w.writerow({"name": "高橋", "age": 22, "city": "福岡"})

print(open("out.csv", newline="", encoding="utf-8").read())

実行結果:

name,age,city
佐藤,28,東京
鈴木,34,大阪
高橋,22,福岡

追記でもfieldnamesは必要です。既存ファイルと同じ順番を渡さないと、列がずれたまま追記されてしまいます。


Excelで開くファイルを作る

日本語の列名を使うなら、BOM付きUTF-8で保存すると文字化けを防げます。

import csv

with open("excel.csv", "w", newline="", encoding="utf-8-sig") as f:
    w = csv.DictWriter(f, fieldnames=["名前", "年齢"])
    w.writeheader()
    w.writerow({"名前": "佐藤", "年齢": 28})

print(open("excel.csv", "rb").read())

実行結果:

b'\xef\xbb\xbf\xe5\x90\x8d\xe5\x89\x8d,\xe5\xb9\xb4\xe9\xbd\xa2\r\n\xe4\xbd\x90\xe8\x97\xa4,28\r\n'

先頭の\xef\xbb\xbfがBOMです。これがあるとExcelがUTF-8として開いてくれます。


書き出したCSVを読み戻す

DictWriterで書いたファイルはDictReaderでそのまま辞書に戻ります。

import csv

with open("out.csv", newline="", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        print(row)

実行結果:

{'name': '佐藤', 'age': '28', 'city': '東京'}
{'name': '鈴木', 'age': '34', 'city': '大阪'}
{'name': '高橋', 'age': '22', 'city': '福岡'}

ageが28ではなく'28'になっている点に注意してください。CSVは型を保存しません。読み込み側は「Python csv.DictReader()とは?CSVを辞書で読み込む方法」で解説しています。


fieldnamesを自動で作る

列名を手で並べるのが面倒なときは、データから作れます。

import csv

rows = [{"name": "佐藤", "age": 28, "city": "東京"},
        {"name": "鈴木", "age": 34, "city": "大阪"}]

with open("auto.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
    w.writeheader()
    w.writerows(rows)

ただし1件目にないキーが2件目以降にあるとValueErrorになります。データがそろっていない可能性があるなら、全件からキーを集めてください。

fields = sorted({k for r in rows for k in r})

csv.DictWriter()のまとめ

  • DictWriterは辞書を1行としてCSVに書き出す
  • fieldnamesは必須。列の順番と対象を決める
  • writeheader()を忘れると列名なしのCSVができる
  • 余分なキーはValueError。捨てるならextrasaction="ignore"
  • 足りないキーは空欄。既定値はrestval
  • 追記は"a"モードでwriteheader()を呼ばない
  • open()にはnewline=""、Excel向けはutf-8-sig

あわせて読みたい

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら