Read a CSV as dictionaries
Reads a CSV file into a list of dictionaries keyed by header row, with the encoding and newline handling that avoids the usual gotchas.
Last updated
import csv
def read_csv_dicts(path):
with open(path, newline="", encoding="utf-8") as f:
return list(csv.DictReader(f))
# rows = read_csv_dicts("users.csv")
# rows[0]["email"]How it works
csv.DictReader turns the first row into field names and every row after it into a dict keyed by those names, so callers read rows[i]["email"] by column name instead of tracking a fragile positional index that breaks the moment a column gets reordered.
The two open() arguments are both there for a specific bug each: newline="" hands the file to the csv module exactly as Python's own docs recommend, so it (not the platform's universal-newlines layer) is the one deciding how embedded newlines inside quoted fields are handled; encoding="utf-8" is stated explicitly rather than left to the platform default, which is ASCII-ish on some Windows locales and would otherwise raise on the first non-ASCII name or accented character.
Edge cases to know
- →list(...) reads the whole file into memory at once — fine for typical CSVs, but for a multi-gigabyte file, iterate the DictReader directly (for row in csv.DictReader(f): ...) instead of collecting it into a list.
- →A CSV saved with a different encoding (e.g. Windows-1252 from older Excel exports) will raise a UnicodeDecodeError with encoding="utf-8" — pass the actual source encoding, or encoding="utf-8-sig" if the file has a BOM.
- →Rows with more or fewer fields than the header get padded with None or collected into a list under the None key rather than raising — check for that key if the source data isn't guaranteed clean.