csv.DictWriter
fieldnames fixes the columns and their order; each dict is looked up key by key. A key the dict lacks is filled with restval, a key fieldnames lacks is an error — and the header line is only written when you call writeheader().
Demo
import csv, io buf = io.StringIO(newline='') w = csv.DictWriter(buf, fieldnames=['name', 'age']) w.writeheader() w.writerow(dict(zip(['name', 'age'], ['Ada', '36']))) buf.getvalue()
Columns always follow fieldnames, whatever order the dict has. A missing key is written as restval ('' by default), so "missing key" ends in two empty fields. An unknown key raises ValueError: dict contains fields not in fieldnames: 'age' — with several unknown keys they are listed in set order, which can change from run to run. In the second tab, the first dict is written before Bob's 'id' key stops writerows, so with 'raise' nothing at all comes out of the demo (the exception is what you see). extrasaction is lower-cased, so 'IGNORE' works; any other word is rejected by the constructor.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| f | object with write() | yes | A file opened with newline='' (or io.StringIO). |
| fieldnames | sequence of keys | yes | The columns, in output order. |
| restval | any | no ('') | Written for a field name the dict has no key for. |
| extrasaction | 'raise' | 'ignore' | no ('raise') | What to do with keys that are not in fieldnames (case-insensitive). |
| dialect | str | Dialect | no ('excel') | Passed to csv.writer with any other keyword arguments (delimiter=…, quoting=…). |
Return value
DictWriter — An object with writeheader(), writerow(rowdict) and writerows(rowdicts); .writer is the underlying csv.writer.
Common patterns
import csv with open('people.csv', 'w', newline='', encoding='utf-8') as f: w = csv.DictWriter(f, fieldnames=['name', 'age']) w.writeheader() w.writerows(people)
import csv with open('export.csv', 'w', newline='', encoding='utf-8') as f: w = csv.DictWriter(f, fieldnames=['id', 'email'], extrasaction='ignore') w.writeheader() w.writerows(users)
import csv fields = list(dict.fromkeys(k for row in rows for k in row)) with open('all.csv', 'w', newline='', encoding='utf-8') as f: w = csv.DictWriter(f, fieldnames=fields) w.writeheader() w.writerows(rows)
Examples
Pitfalls
import csv, io buf = io.StringIO(newline='') w = csv.DictWriter(buf, ['name', 'age']) w.writerow({'name': 'Ada', 'age': 36}) buf.getvalue()
import csv, io buf = io.StringIO(newline='') w = csv.DictWriter(buf, ['name', 'age']) w.writeheader() w.writerow({'name': 'Ada', 'age': 36}) buf.getvalue()
import csv, io csv.DictWriter(io.StringIO(), ['a', 'b']).writerow(['x', 'y'])
import csv, io buf = io.StringIO(newline='') csv.writer(buf).writerow(['x', 'y']) buf.getvalue()
import csv, io rows = [{'a': 1}, {'a': 2, 'b': 3}] w = csv.DictWriter(io.StringIO(), fieldnames=rows[0].keys()) w.writerows(rows)
import csv, io rows = [{'a': 1}, {'a': 2, 'b': 3}] buf = io.StringIO(newline='') w = csv.DictWriter(buf, fieldnames=list(dict.fromkeys(k for r in rows for k in r))) w.writerows(rows) buf.getvalue()
When to use
- Your data is already a list of dicts (JSON records, database rows)
- You want a fixed column order regardless of dict order
- Rows that are lists → csv.writer
- Nested values (dicts inside dicts) → json, or flatten first
Notes
FAQ
Open the file with newline='', create csv.DictWriter(f, fieldnames=[...]), call writeheader(), then writerows(list_of_dicts).