CSV and Text
CSV to Dicts
Convert parsed CSV rows into a list of dicts by zipping the header row with
each data row. The trace shows rec being built fresh for each row via
dict(zip(header, fields)) before being appended to records.
By hand
Split lines as in parse-csv-rows, treat the first line as the header, then
for each data line build a dict with dict(zip(header, line.split(','))).
records is ignored in the trace so the per-row rec dict is visible.
naive.py
Replay: real traced execution (multi-file project)
csv_text = 'id,cat,val\n1,x,10\n2,y,20\n3,x,30'
lines = csv_text.split('\n')
header = lines[0].split(',')
records = []
# trace: ignore records
for line in lines[1:]:
rec = dict(zip(header, line.split(',')))
records.append(rec)
print('RESULT:', records[-1])
csv_text ← 'id,cat,val\n1,x,10\n2,y,20\n3,x,30'
1csv_text = 'id,cat,val\n1,x,10\n2,y,20\n3,x,30'2lines = csv_text.split('\n')values this step'id,cat,val\n1,x,10\n2,y,20\n3,x,30'csv_textlines ← ['id,cat,val', '1,x,10', '2,y,20', '3,x,30']
1csv_text = 'id,cat,val\n1,x,10\n2,y,20\n3,x,30'2lines = csv_text.split('\n')3header = lines[0].split(',')values this step['id,cat,val', '1,x,10', '2,y,20', '3,x,30']linesheader ← ['id', 'cat', 'val']
2lines = csv_text.split('\n')3header = lines[0].split(',')4records = []values this step['id', 'cat', 'val']headerrecords = []
3header = lines[0].split(',')4records = []5# trace: ignore recordsline ← '1,x,10'
5# trace: ignore records6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))values this step'1,x,10'linerec ← {'id': '1', 'cat': 'x', 'val': '10'}
6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))8 records.append(rec)values this step{'id': '1', 'cat': 'x', 'val': '10'}recrecords.append(rec)
7 rec = dict(zip(header, line.split(',')))8 records.append(rec)9print('RESULT:', records[-1])line ← '2,y,20'
5# trace: ignore records6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))values this step'1,x,10' → '2,y,20'linerec ← {'id': '2', 'cat': 'y', 'val': '20'}
6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))8 records.append(rec)values this step{'id': '1', 'cat': 'x', 'val': '10'} → {'id': '2', 'cat': 'y', 'val': '20'}recrecords.append(rec)
7 rec = dict(zip(header, line.split(',')))8 records.append(rec)9print('RESULT:', records[-1])line ← '3,x,30'
5# trace: ignore records6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))values this step'2,y,20' → '3,x,30'linerec ← {'id': '3', 'cat': 'x', 'val': '30'}
6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))8 records.append(rec)values this step{'id': '2', 'cat': 'y', 'val': '20'} → {'id': '3', 'cat': 'x', 'val': '30'}recrecords.append(rec)
7 rec = dict(zip(header, line.split(',')))8 records.append(rec)9print('RESULT:', records[-1])for line in lines[1:]:
5# trace: ignore records6for line in lines[1:]:7 rec = dict(zip(header, line.split(',')))stdout ← RESULT: {'id': '3', 'cat': 'x', 'val': '30'}
8 records.append(rec)9print('RESULT:', records[-1])values this stepRESULT: {'id': '3', 'cat': 'x', 'val': '30'}stdout
The Pythonic way
csv.DictReader reads the header automatically and yields one dict per data
row. list(...) materialises the result.
library.py
import csv
import io
csv_text = 'id,cat,val\n1,x,10\n2,y,20\n3,x,30'
records = list(csv.DictReader(io.StringIO(csv_text)))
print('RESULT:', records[-1])
RESULT: {'id': '3', 'cat': 'x', 'val': '30'}
Implementation notes
- RESULT prints the last dict; the full list of 3 dicts would exceed the 80-char repr limit.
dict(zip(header, fields))is the building block behindcsv.DictReader— both pair column names with values positionally.- All field values are strings after CSV parsing; use
int(rec['val'])or similar to convert numeric columns. - See
parse-csv-rows(this chapter) for the prior step that produces the raw row lists this lesson consumes.