csv.DictReader
The first row becomes the keys, every later row a dict. Blank lines are skipped, a short row is padded with restval, and a long row puts its extra values in a list under the key None.
Demo
import csv, io text = 'name,age\\nAda,36\\nBob,41'.replace('\\n', '\n') list(csv.DictReader(io.StringIO(text, newline='')))
A repeated column name keeps the LAST value (dict(zip(...)) overwrites) but the first position. A header with no data rows gives []. With fieldnames=[] every value counts as "extra": the dict holds a single key, None. In restkey / restval the long row 1,2,3,4 keeps ["3", "4"] under None and the short row 5 gets None for b — the dict itself never complains, which is how wrong delimiters go unnoticed.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| f | iterable of str | yes | A file opened with newline='' (or any iterable of lines). |
| fieldnames | sequence of str | no (None) | The keys. None reads them from the first row; given, the first row is treated as data. |
| restkey | hashable | no (None) | Key for the list of values beyond the last field name. |
| restval | any | no (None) | Value for field names that a short row has no value for. |
| dialect | str | Dialect | no ('excel') | Passed to csv.reader together with any other keyword arguments (delimiter=…). |
Return value
DictReader — An iterator of dicts, one per non-blank row. .fieldnames holds the keys; .line_num and .reader are also available.
Common patterns
import csv with open('people.csv', newline='', encoding='utf-8-sig') as f: people = list(csv.DictReader(f))
import csv with open('people.csv', newline='', encoding='utf-8') as f: people = [{**row, 'age': int(row['age'])} for row in csv.DictReader(f)]
import csv with open('people.csv', newline='', encoding='utf-8') as f: rows = csv.DictReader(f) missing = {'name', 'age'} - set(rows.fieldnames or []) if missing: raise ValueError(f'missing columns: {missing}')
Examples
Pitfalls
import csv next(csv.DictReader(['name;age', 'Ada;36']))
import csv next(csv.DictReader(['name;age', 'Ada;36'], delimiter=';'))
import csv with open('b.csv', 'w', encoding='utf-8-sig', newline='') as f: f.write('name,age\r\nAda,36\r\n') with open('b.csv', encoding='utf-8', newline='') as f: name = next(csv.DictReader(f))['name']
import csv with open('b.csv', 'w', encoding='utf-8-sig', newline='') as f: f.write('name,age\r\nAda,36\r\n') with open('b.csv', encoding='utf-8-sig', newline='') as f: name = next(csv.DictReader(f))['name'] name
import csv list(next(csv.DictReader(['name, age', 'Ada, 36'])))
import csv list(next(csv.DictReader(['name, age', 'Ada, 36'], skipinitialspace=True)))
When to use
- Files with a header row where you want columns by name
- Code that should survive reordered columns
- Files without a header and fixed positions → csv.reader is simpler
- Typed data and analysis → pandas.read_csv
Notes
FAQ
with open(path, newline='', encoding='utf-8') as f: rows = list(csv.DictReader(f)). Each dict maps the header names to that row's values (all strings).