Skip to content
datarekha
Python Easy Asked at AmazonAsked at Databricks

Write Python to read a CSV file line by line and compute a column aggregate without loading the entire file into memory.

The short answer

Using the csv module with a generator or a running accumulator keeps memory use constant — O(1) space — regardless of file size. This matters when files are larger than available RAM, a common situation in data engineering pipelines.

How to think about it

The interviewer is checking two things: can you drive the csv module correctly, and do you grasp the memory difference between iterating row by row and loading the whole file at once. The load-bearing phrase is “without loading the entire file into memory” — that’s the cue to keep a running accumulator, not reach for pd.read_csv.

A worked example

A csv.DictReader wraps a file handle, which is itself a lazy iterator — so reading row by row holds exactly one row in memory at a time. (Here the file is a StringIO so the example is self-contained; the logic is identical against a real open().)

import csv
import io
from collections import defaultdict

CSV_DATA = """region,product,revenue
North,Widget,120.50
South,Gadget,340.00
North,Gadget,95.25
South,Widget,210.75
North,Widget,88.00
South,Gadget,150.50
"""

# Simple column sum — one row at a time, O(1) memory
def sum_column(fileobj, col):
    total = 0.0
    for row in csv.DictReader(fileobj):
        total += float(row[col])
    return total

print("Total revenue:", sum_column(io.StringIO(CSV_DATA), "revenue"))

# Group-by aggregate — still a single streaming pass
def sum_by_group(fileobj, group_col, value_col):
    totals = defaultdict(float)
    for row in csv.DictReader(fileobj):
        totals[row[group_col]] += float(row[value_col])
    return dict(totals)

print("By region:", sum_by_group(io.StringIO(CSV_DATA), "region", "revenue"))
print("By product:", sum_by_group(io.StringIO(CSV_DATA), "product", "revenue"))
Total revenue: 1005.0
By region: {'North': 303.75, 'South': 701.25}
By product: {'Widget': 419.25, 'Gadget': 585.75}

Both functions did their work in one streaming pass. sum_column carried a single running float; sum_by_group kept only one accumulator per group (a handful of keys), never the rows themselves. So the memory cost is set by the number of groups, not the size of the file — the same code totals a 1 KB file or a 1 TB one without change.

The real-file version

Against an actual file it’s the same loop inside a with block:

import csv
from collections import defaultdict

def sum_column(filepath: str, col: str) -> float:
    total = 0.0
    with open(filepath, newline="", encoding="utf-8") as fh:
        for row in csv.DictReader(fh):
            total += float(row[col])
    return total

Two details earn their keep: newline="" lets the csv module handle line endings correctly across platforms (don’t pass "\n"), and the with block guarantees the file closes even if a row mid-stream raises.

Learn it properly Functions

Keep practising

All Python questions

Explore further