Python | ファイル・OS 操作:CSV DictWriter

Python Python
スポンサーリンク

概要(DictWriterは「列名で書ける」CSV出力の定番)

csv.DictWriterは、辞書(dict)をそのままCSVの行として書き込める標準機能です。列順やヘッダーを明示できるため、インデックスを意識せず「列名=キー」で安全・読みやすく出力できます。重要なのは「fieldnames(列名)の設計」「ヘッダーの書き出し」「欠損キー・余分キーの扱い」「改行とエンコーディング」です。with文で開いてnewline=”にするのが基本で、DictReaderと組み合わせると“読み→加工→書き”が自然につながります。


基本の使い方(ここが重要)

ヘッダー付きで辞書を行として書き込む

import csv

data = [
    {"name": "Alice", "age": 30, "city": "New York"},
    {"name": "Bob",   "age": 25, "city": "Los Angeles"},
]

with open("output.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "age", "city"])
    writer.writeheader()                # 最初にヘッダー行を書く
    for row in data:
        writer.writerow(row)            # 辞書のキーを列名に対応させて1行書く
Python

newline=”は改行の二重発生(空行が入る問題)を防ぐための推奨設定です。fieldnamesは「列の順序と必須キー」を決めます。

Pathlibと組み合わせて安全に出力先を用意

from pathlib import Path
import csv

out = Path("reports/users.csv")
out.parent.mkdir(parents=True, exist_ok=True)

with out.open("w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["id", "name", "age"])
    writer.writeheader()
    writer.writerow({"id": 101, "name": "alice", "age": 30})
Python

重要ポイントの深掘り(fieldnames・ヘッダー・欠損と余分・改行と文字コード)

fieldnames(列名)の決め方と整合性

  • 列順の固定: fieldnamesの順がそのままCSVの列順になるので、読み手や後工程が想定する順番で定義します。
  • 必須列の宣言: “必ず存在するキー”をfieldnamesに含め、欠損時の扱い(後述)をポリシー化します。
  • 追加列の管理: 加工で列が増える場合は、事前にfieldnamesへ追加してからwriteheaderを呼びます。

writeheader(ヘッダー出力)は“最初に一度だけ”

  • 明示的に出す: ファイル先頭に必ずヘッダーが必要なら、writeheaderを最初に実行。
  • 追記モードでは重複回避: 追記(”a”)では既存ヘッダー有無を確認し、二重に書かない工夫が必要です。

欠損キー・余分キーの扱い(extrasaction / restval)

import csv

rows = [
    {"id": 1, "name": "a"},                         # age 欠損
    {"id": 2, "name": "b", "age": 20, "city": "X"}  # city は余分
]

with open("out.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(
        f,
        fieldnames=["id", "name", "age"],
        extrasaction="ignore"   # 余分キーは無視(例:cityを捨てる)
    )
    writer.writeheader()
    for row in rows:
        writer.writerow(row)     # age 欠損は空セルになる
Python
  • 欠損キー: 指定列に対して辞書にキーが無い場合、そのセルは空文字で書かれます。必要なら前処理でデフォルト値をセット。
  • 余分キー: extrasaction=”ignore”なら無視、未指定のまま余分キーがあるとValueErrorになるため、ポリシーを統一します。
  • restval(DictReader側の概念)との違い: 書き込みにはrestvalは無く、欠損は空になります。書く前に欠損補完するのが安全です。

改行と文字コード(Excelなどの互換を意識)

  • newline=” を徹底: csvモジュールは改行を自身で制御するため、openでnewline=”が必須。
  • encoding: 迷ったらutf-8。WindowsでExcel互換を強めたい場合はutf-8-sig(BOM付き)で先頭の文字化け回避を考慮。

実務の使いどころ(加工出力・追記・列の追加・方言)

読み→加工→書き(DictReaderと直結)

import csv

with open("input.csv", newline="", encoding="utf-8") as fin, \
     open("output.csv", "w", newline="", encoding="utf-8") as fout:
    reader = csv.DictReader(fin)
    fieldnames = reader.fieldnames + ["score2"]  # 新列を増やす
    writer = csv.DictWriter(fout, fieldnames=fieldnames)
    writer.writeheader()
    for row in reader:
        row["score2"] = float(row["score"]) * 2 if row.get("score") else ""
        writer.writerow(row)
Python

DictReaderで辞書を受け、そのままDictWriterへ。列追加・欠損補完が分かりやすく書けます。

既存ファイルへの追記(ヘッダー重複の防止)

import csv
from pathlib import Path

path = Path("log.csv")
exists = path.exists()

with path.open("a", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["time", "event"])
    if not exists:
        writer.writeheader()
    writer.writerow({"time": "2025-12-15 17:06", "event": "start"})
Python

新規作成時だけヘッダーを書き、既存にはデータだけ追記します。

区切り文字・引用符の指定(dialectの調整)

import csv

rows = [{"a": 1, "b": 'hello, "world"'}]

with open("semi.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(
        f,
        fieldnames=["a", "b"],
        delimiter=";",      # セミコロン区切り
        quotechar='"',
        quoting=csv.QUOTE_MINIMAL
    )
    writer.writeheader()
    for r in rows:
        writer.writerow(r)
Python

Excelや他システム由来の仕様に合わせ、delimiter・quotechar・quoting・escapecharを調整します。


例題で身につける(定番から一歩先まで)

例題1:欠損値をデフォルト補完して書く

import csv

rows = [{"id": 1, "name": "A"}, {"id": 2, "name": "B", "age": 20}]
def fill_defaults(row):
    return {"id": row.get("id", ""), "name": row.get("name", ""), "age": row.get("age", 0)}

with open("filled.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["id", "name", "age"])
    writer.writeheader()
    for r in rows:
        writer.writerow(fill_defaults(r))
Python

例題2:余分キーを拒否(厳格モード)

import csv

rows = [{"id": 1, "name": "A", "age": 20}, {"id": 2, "name": "B", "age": 30, "city": "X"}]

with open("strict.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["id", "name", "age"])  # extrasactionを指定しない
    writer.writeheader()
    for r in rows:
        writer.writerow(r)  # 2行目で ValueError(余分キー)→ 例外で気付ける
Python

例題3:BOM付きでExcel互換を上げる

import csv

with open("excel.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.DictWriter(f, fieldnames=["Name", "Age"])
    writer.writeheader()
    writer.writerow({"Name": "Taro", "Age": 25})
Python

例題4:加工で列順を制御(表示・下流連携のため)

import csv

rows = [{"name": "Alice", "city": "NY", "age": 30},
        {"name": "Bob",   "city": "LA", "age": 25}]

order = ["name", "age", "city"]  # 列順ポリシー

with open("ordered.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=order)
    w.writeheader()
    for r in rows:
        w.writerow({k: r.get(k, "") for k in order})
Python

まとめ

DictWriterは「列名でデータを書く」ための最短手段で、列順とヘッダーを明示できるのが最大の強みです。fieldnamesで順序と必須列を決め、writeheaderを冒頭で一度だけ。欠損キーは空になるため前処理で補完し、余分キーはextrasaction=”ignore”か厳格に例外で気付く設計にする。newline=”と適切なencodingを守り、必要ならdelimiterやquotingを調整。DictReaderと組み合わせて“読み→加工→書き”を一貫させれば、初心者でも短くて安全なCSV出力が書けます。

タイトルとURLをコピーしました