CSV and Text
Parse CSV Rows
Split a CSV string into a list of row lists by breaking on newlines and
then on commas. The trace shows rows growing one split row at a time,
with the header row appearing as the first element.
By hand
Split the CSV string on '\n' to get lines, then split each line on ','
to get fields. Append each field list to rows.
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')
rows = []
for line in lines:
rows.append(line.split(','))
print('RESULT:', (len(rows), rows[-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')3rows = []values this step['id,cat,val', '1,x,10', '2,y,20', '3,x,30']linesrows ← []
2lines = csv_text.split('\n')3rows = []4for line in lines:values this step[]rowsline ← 'id,cat,val'
3rows = []4for line in lines:5 rows.append(line.split(','))values this step'id,cat,val'linerows ← [['id', 'cat', 'val']]
4for line in lines:5 rows.append(line.split(','))6print('RESULT:', (len(rows), rows[-1]))values this step[] → [['id', 'cat', 'val']]rowsline ← '1,x,10'
3rows = []4for line in lines:5 rows.append(line.split(','))values this step'id,cat,val' → '1,x,10'linerows ← [['id', 'cat', 'val'], ['1', 'x', '10']]
4for line in lines:5 rows.append(line.split(','))6print('RESULT:', (len(rows), rows[-1]))values this step[['id', 'cat', 'val']] → [['id', 'cat', 'val'], ['1', 'x', '10']]rowsline ← '2,y,20'
3rows = []4for line in lines:5 rows.append(line.split(','))values this step'1,x,10' → '2,y,20'linerows ← [['id', 'cat', 'val'], ['1', 'x', '10'], ['2', 'y', '20']]
4for line in lines:5 rows.append(line.split(','))6print('RESULT:', (len(rows), rows[-1]))values this step[['id', 'cat', 'val'], ['1', 'x', '10']] → [['id', 'cat', 'val'], ['1', 'x', '10'], ['2', 'y', '20']]rowsline ← '3,x,30'
3rows = []4for line in lines:5 rows.append(line.split(','))values this step'2,y,20' → '3,x,30'linerows ← [['id', 'cat', 'val'], ['1', 'x', '10'], ['2', 'y', '20'], ['3', 'x', '30']]
4for line in lines:5 rows.append(line.split(','))6print('RESULT:', (len(rows), rows[-1]))values this step[['id', 'cat', 'val'], ['1', 'x', '10'], ['2', 'y', '20']] → [['id', 'cat', 'val'], ['1', 'x', '10'], ['2', 'y', '20'], ['3', 'x', '30']]rowsfor line in lines:
3rows = []4for line in lines:5 rows.append(line.split(','))stdout ← RESULT: (4, ['3', 'x', '30'])
5 rows.append(line.split(','))6print('RESULT:', (len(rows), rows[-1]))values this stepRESULT: (4, ['3', 'x', '30'])stdout
The Pythonic way
csv.reader wraps an io.StringIO text stream and handles splitting
automatically. list(reader) materialises all rows at once.
library.py
import csv
import io
csv_text = 'id,cat,val\n1,x,10\n2,y,20\n3,x,30'
rows = list(csv.reader(io.StringIO(csv_text)))
print('RESULT:', (len(rows), rows[-1]))
RESULT: (4, ['3', 'x', '30'])
Implementation notes
- RESULT prints
(row_count, last_row)— the full list of 4 rows would exceed the 80-char trace limit, so only the count and last row are shown. .split(',')breaks on every comma, including commas inside quoted fields;csv.readerhandles quoting correctly. For simple numeric data without embedded commas the manual split is equivalent.- See
csv-to-dicts(this chapter) for the next step: mapping each row to a dict using the header row.