Accessing row['email'] instead of row[3] keeps code correct when columns are added or reordered.
`csv.DictReader(f)` uses the first row as field names and yields each following row as a dict: row["email"]. Since Python 3.8 these are plain dicts, in column order.
reader.fieldnamesgives the header.- Pass
fieldnames=[...]if the file has no header row; then the first row is treated as data. - If a row has more fields than the header, extras go into a list under the
restkey(defaultNone); missing fields getrestval(defaultNone).
`csv.DictWriter(f, fieldnames=[...])` writes dicts:
writer.writeheader()writes the field names row; call it once.writer.writerow(d)/writerows(dicts): keys are matched to columns; missing keys getrestval(default empty).- A dict with a key not in
fieldnamesraisesValueError, unless you passextrasaction="ignore".
fieldnames also controls column order in the output, so you can reorder or select columns when transforming files. A typical pipeline reads with DictReader, transforms each dict, and writes with DictWriter, streaming row by row.
Example
import csv
with open("users.csv", "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=["id", "email", "plan"])
w.writeheader()
w.writerow({"id": 1, "email": "ada@x.io", "plan": "pro"})
w.writerow({"id": 2, "email": "bob@x.io"}) # plan -> ''
with open("users.csv", newline="", encoding="utf-8") as f, \
open("emails.csv", "w", newline="", encoding="utf-8") as out:
reader = csv.DictReader(f)
print(reader.fieldnames) # ['id', 'email', 'plan']
writer = csv.DictWriter(out, fieldnames=["email", "id"], extrasaction="ignore")
writer.writeheader()
for row in reader:
print(row) # {'id': '1', 'email': 'ada@x.io', 'plan': 'pro'} ...
writer.writerow(row) # 'plan' ignored, columns reordered
print(open("emails.csv").read().split()) # ['email,id', 'ada@x.io,1', 'bob@x.io,2']Remember
- DictReader yields one dict per row, keyed by the header
- DictWriter needs fieldnames and writeheader()
- extrasaction='ignore' drops keys that aren't columns
Watch out for
- Forgetting writeheader(), producing a file without column names.