Chapters
Python114 chapters

Files and errorsChapter 85 of 114

CSV Files

Read and write comma-separated data without breaking on quoted commas.

Do not split on commas

A real CSV can hold commas inside quoted fields, and splitting by hand cuts them in half:

Python
line = 'Ada,"maths, and computing",1815'

print(line.split(","))

Output

['Ada', '"maths', ' and computing"', '1815']

Three fields became four. The csv module knows the rules:

Python
import csv
import io

line = 'Ada,"maths, and computing",1815'
print(next(csv.reader(io.StringIO(line))))

Output

['Ada', 'maths, and computing', '1815']

Writing

Python
import csv

rows = [["name", "born"], ["Ada", 1815], ["Grace", 1906]]

with open("people.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

with open("people.csv", encoding="utf-8") as f:
    print(f.read().strip())

Output

name,born
Ada,1815
Grace,1906

Reading rows

Python
import csv

with open("people.csv", "w", encoding="utf-8", newline="") as f:
    csv.writer(f).writerows([["name", "born"], ["Ada", 1815]])

with open("people.csv", encoding="utf-8", newline="") as f:
    for row in csv.reader(f):
        print(row)

Output

['name', 'born']
['Ada', '1815']

Note '1815' is a string. CSV has no types — everything comes back as text, and converting is your job.

DictReader is usually what you want

It uses the header row, so you read by column name rather than by position:

Python
import csv

with open("people.csv", "w", encoding="utf-8", newline="") as f:
    csv.writer(f).writerows([["name", "born"], ["Ada", 1815], ["Grace", 1906]])

with open("people.csv", encoding="utf-8", newline="") as f:
    for row in csv.DictReader(f):
        print(row["name"], int(row["born"]) + 100)

Output

Ada 1915
Grace 2006

Now inserting a column in the file cannot break your code.

DictWriter

Python
import csv

people = [
    {"name": "Ada", "born": 1815},
    {"name": "Grace", "born": 1906},
]

with open("people.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "born"])
    writer.writeheader()
    writer.writerows(people)

with open("people.csv", encoding="utf-8") as f:
    print(f.read().strip())

Output

name,born
Ada,1815
Grace,1906

fieldnames fixes the column order and, by default, a key not in that list raises rather than being silently dropped.

Other separators

Python
import csv

with open("data.tsv", "w", encoding="utf-8", newline="") as f:
    csv.writer(f, delimiter="\t").writerow(["a", "b"])

with open("data.tsv", encoding="utf-8", newline="") as f:
    print(next(csv.reader(f, delimiter="\t")))

Output

['a', 'b']

Semicolons are common in countries where the comma is the decimal separator, so delimiter=";" comes up often with spreadsheet exports.

Large files

A reader is an iterator, so it never loads the whole file:

Python
import csv

with open("big.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["n"])
    writer.writerows([[i] for i in range(1000)])

total = 0
with open("big.csv", encoding="utf-8", newline="") as f:
    for row in csv.DictReader(f):
        total += int(row["n"])

print(total)

Output

499500

That works the same on a file of ten million rows.

Test yourself

2 questions

Why not split a CSV line on commas yourself?

Show the answer

A quoted field can contain a comma — The csv module knows the quoting rules. Splitting by hand cuts a quoted field in half.

Why pass newline="" when opening a CSV?

Show the answer

Otherwise line endings are translated and rows come out blank — Pass it for reading too, so quoted fields containing newlines survive.

Next chapter

Context Managers

Guarantee that cleanup happens, even when something goes wrong.