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]))
  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_text
  2. lines ← ['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']lines
  3. rows ← []

    2lines = csv_text.split('\n')3rows = []4for line in lines:
    values this step[]rows
  4. line ← 'id,cat,val'

    3rows = []4for line in lines:5    rows.append(line.split(','))
    values this step'id,cat,val'line
  5. rows ← [['id', 'cat', 'val']]

    4for line in lines:5    rows.append(line.split(','))6print('RESULT:', (len(rows), rows[-1]))
    values this step[] [['id', 'cat', 'val']]rows
  6. line ← '1,x,10'

    3rows = []4for line in lines:5    rows.append(line.split(','))
    values this step'id,cat,val' '1,x,10'line
  7. rows ← [['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']]rows
  8. line ← '2,y,20'

    3rows = []4for line in lines:5    rows.append(line.split(','))
    values this step'1,x,10' '2,y,20'line
  9. rows ← [['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']]rows
  10. line ← '3,x,30'

    3rows = []4for line in lines:5    rows.append(line.split(','))
    values this step'2,y,20' '3,x,30'line
  11. rows ← [['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']]rows
  12. for line in lines:

    3rows = []4for line in lines:5    rows.append(line.split(','))
  13. 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.reader handles 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.