Use the csv module from the standard library. DictReader reads the header line for you and gives back each row as a dictionary, so you write row["city"] instead of remembering that the city was column 2.
# Make a small file to read. Skip this part if you already have one. with open("people.csv", "w", newline="", encoding="utf-8") as f: f.write("name,city,age\nAda,London,36\nLinus,Helsinki,28\nGrace,New York,45\n") import csv with open("people.csv", newline="", encoding="utf-8") as f: for row in csv.DictReader(f): print(row["name"], "lives in", row["city"])
Ada lives in London Linus lives in Helsinki Grace lives in New York
Every value is a string
The CSV format has no idea what a number is. "36" comes back as text, and adding to it fails or, worse, quietly does string things.
import csv, io data = io.StringIO("name,age\nAda,36\nLinus,28\n") # behaves like an open file ages = [int(row["age"]) for row in csv.DictReader(data)] print(sum(ages) / len(ages))
32.0
Convert at the moment you read, once, and the rest of the program can trust the types.
With pandas, for anything you'll analyse
If the next thing you'll do is filter, group or average, read it straight into a DataFrame. pandas also works out the column types for you. (The first Run here takes a few seconds while pandas downloads.)
import io import pandas as pd data = io.StringIO("name,city,age\nAda,London,36\nLinus,Helsinki,28\nGrace,New York,45\n") df = pd.read_csv(data) # or pd.read_csv("people.csv") print(df["age"].mean()) print(df[df["age"] > 30]["name"].tolist())
36.333333333333336 ['Ada', 'Grace']
The two things that bite
- A file saved from Excel often starts with an invisible byte-order mark, and your first column turns into
'\ufeffname', sorow["name"]raisesKeyError. Open it withencoding="utf-8-sig"and the mark is dropped. UnicodeDecodeErrormeans the file isn't UTF-8 at all, usually an old Windows export. Tryencoding="cp1252"; the error page explains how to tell.
Always pass newline="" when you open a CSV. The csv module handles line endings itself, and without it a quoted field containing a line break gets split in two.