Python csv — Read & Write CSV
CSV (Comma-Separated Values) is the universal format for tabular data — spreadsheets, exports, datasets. The csvcsv module reads and writes it correctly, handling quoting, commas inside fields, and newlines that naive string splitting would get wrong.
import csv
import io
# Read rows from CSV text
text = "name,age\nAda,36\nBob,25"
reader = csv.reader(io.StringIO(text))
for row in reader:
print(row)
# ['name', 'age']
# ['Ada', '36']
# ['Bob', '25']import csv
import io
# Read rows from CSV text
text = "name,age\nAda,36\nBob,25"
reader = csv.reader(io.StringIO(text))
for row in reader:
print(row)
# ['name', 'age']
# ['Ada', '36']
# ['Bob', '25']Always open files with
newline=""newline=""when usingcsvcsv. This lets the module handle line endings itself and prevents blank rows on Windows.
The four tools
| Tool | Direction | Row shape |
|---|---|---|
csv.reader(file)csv.reader(file) | Read | Each row is a list. |
csv.writer(file)csv.writer(file) | Write | You pass lists. |
csv.DictReader(file)csv.DictReader(file) | Read | Each row is a dict keyed by header. |
csv.DictWriter(file, fieldnames)csv.DictWriter(file, fieldnames) | Write | You pass dicts. |
Writing with csv.writer
import csv
rows = [
["name", "city"],
["Ada", "London"],
["Bob", "New York, NY"], # comma inside a field is handled automatically
]
with open("people.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["title", "year"]) # one row
writer.writerows(rows) # many rowsimport csv
rows = [
["name", "city"],
["Ada", "London"],
["Bob", "New York, NY"], # comma inside a field is handled automatically
]
with open("people.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["title", "year"]) # one row
writer.writerows(rows) # many rowsThe module quotes fields that contain commas, quotes, or newlines, so "New York, NY""New York, NY" stays a single field.
Reading with csv.reader
import csv
with open("people.csv", "r", newline="", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader) # pull the header row off first
print("Header:", header)
for row in reader:
print(row) # each row is a list of stringsimport csv
with open("people.csv", "r", newline="", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader) # pull the header row off first
print("Header:", header)
for row in reader:
print(row) # each row is a list of stringsEvery value read from CSV is a string. Convert numbers yourself:
int(row[1])int(row[1]),float(row[2])float(row[2]).
DictReader — rows as dictionaries
DictReaderDictReader uses the first row as keys, so you access columns by name instead of position.
import csv
import io
text = "name,age,city\nAda,36,London\nBob,25,NYC"
reader = csv.DictReader(io.StringIO(text))
for row in reader:
print(row["name"], "is", row["age"])
# Ada is 36
# Bob is 25import csv
import io
text = "name,age,city\nAda,36,London\nBob,25,NYC"
reader = csv.DictReader(io.StringIO(text))
for row in reader:
print(row["name"], "is", row["age"])
# Ada is 36
# Bob is 25DictWriter — write dictionaries
DictWriterDictWriter needs fieldnamesfieldnames; call writeheader()writeheader() to emit the header row.
import csv
people = [
{"name": "Ada", "age": 36},
{"name": "Bob", "age": 25},
]
with open("out.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["name", "age"])
writer.writeheader()
writer.writerows(people)import csv
people = [
{"name": "Ada", "age": 36},
{"name": "Bob", "age": 25},
]
with open("out.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["name", "age"])
writer.writeheader()
writer.writerows(people)Custom delimiters and dialects
Not every “CSV” uses commas. Pass delimiterdelimiter for TSV (tabs), semicolons, or pipes.
import csv
import io
tsv = "name\tage\nAda\t36"
reader = csv.reader(io.StringIO(tsv), delimiter="\t")
print(list(reader)) # [['name', 'age'], ['Ada', '36']]import csv
import io
tsv = "name\tage\nAda\t36"
reader = csv.reader(io.StringIO(tsv), delimiter="\t")
print(list(reader)) # [['name', 'age'], ['Ada', '36']]| Parameter | Controls |
|---|---|
delimiterdelimiter | Field separator (default ,,). |
quotecharquotechar | Character used to quote fields (default ""). |
quotingquoting | When to quote (csv.QUOTE_MINIMALcsv.QUOTE_MINIMAL, QUOTE_ALLQUOTE_ALL, …). |
escapecharescapechar | Escape character for special chars. |
Common pitfalls
- Missing
newline=""newline=""— causes blank rows between every record on Windows. - Forgetting values are strings —
row["age"] + 1row["age"] + 1fails; convert withint(...)int(...)first. DictWriterDictWriterwithoutwriteheader()writeheader()— produces a file with no header row.- Mismatched
fieldnamesfieldnames— a dict key not infieldnamesfieldnamesraisesValueErrorValueError.
Practice Exercises
Exercise 1 – Parse CSV text
Exercise 2 – Sum a numeric column
Exercise 3 – Write rows to CSV text
Summary
- The
csvcsvmodule handles quoting and embedded commas/newlines that manual splitting breaks. - Use
readerreader/writerwriterfor lists,DictReaderDictReader/DictWriterDictWriterfor dicts keyed by header. - Open files with
newline=""newline=""and an explicitencodingencoding. - Remember every read value is a string — convert numbers yourself.
- Set
delimiterdelimiterfor TSV and other separated formats.
If this helped you, consider buying me a coffee ☕
Buy me a coffeeWas this page helpful?
Let us know how we did
