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



