How to Read and Write CSV Files in Python
CSV files are the common language of spreadsheets, bank exports, and sign-up forms. They look simple, just values separated by commas, so the first instinct is to read each line and split on the comma. That works until a value contains a comma of its own. Python's built-in csv module handles those cases for you. Four tools cover most needs, shown here with a small sales file. Every example was run in Python 3 with its real output shown.
1. Why not just split on commas?
Here is one line of a sales file where the customer name contains a comma:
line = '2026-10-02,"Smith, Jo",75.50'
print(line.split(","))
['2026-10-02', '"Smith', ' Jo"', '75.50']
You wanted three fields and got four. CSV files protect commas inside values by wrapping the value in quotes, and a plain split() does not understand that rule. The csv module does.
2. Writing a CSV file with csv.writer
To have a file to work with, create one. Save this as a script and run it:
import csv
rows = [
["date", "customer", "amount"],
["2026-10-01", "Northwind", "120.00"],
["2026-10-02", "Smith, Jo", "75.50"],
["2026-10-02", "Blue Cafe", "42.25"],
]
with open("sales.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(rows)
The file it creates looks like this:
date,customer,amount
2026-10-01,Northwind,120.00
2026-10-02,"Smith, Jo",75.50
2026-10-02,Blue Cafe,42.25
The writer added quotes around "Smith, Jo" automatically and left the other values alone. writerows() writes a whole list of rows. For one row at a time, use writerow().
Notice newline="" in open(). The open() documentation explains that this argument controls how line endings are handled, and the csv documentation says a file used with the csv module should be opened this way. Its footnote explains why: without it, newlines inside quoted fields are not read correctly, and on systems that end lines with \r\n, such as Windows, an extra \r gets added when writing. The documentation adds that it should always be safe to specify newline="", because the csv module does its own newline handling.
3. Reading with csv.reader
import csv
with open("sales.csv", newline="") as f:
reader = csv.reader(f)
for row in reader:
print(row)
['date', 'customer', 'amount']
['2026-10-01', 'Northwind', '120.00']
['2026-10-02', 'Smith, Jo', '75.50']
['2026-10-02', 'Blue Cafe', '42.25']
Each row is a list, and "Smith, Jo" correctly stays in one piece.
4. Every value is text
Look closely at the amounts: '120.00' has quotes around it. The documentation states that each row is returned as a list of strings and that no automatic data type conversion is performed. Trying to add them up directly fails:
import csv
total = 0
with open("sales.csv", newline="") as f:
reader = csv.reader(f)
header = next(reader)
for row in reader:
total += row[2]
print(total)
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
Convert with float() before doing math:
import csv
total = 0
with open("sales.csv", newline="") as f:
reader = csv.reader(f)
header = next(reader)
for row in reader:
total += float(row[2])
print(header)
print(f"{total:.2f}")
['date', 'customer', 'amount']
237.75
next(reader) pulls off the first row, the header, so the loop only sees data rows. 120.00 + 75.50 + 42.25 = 237.75.
5. Reading by column name with DictReader
Counting column positions gets fragile when a file has many columns or someone reorders them. csv.DictReader turns each row into a dictionary. The documentation explains that if you do not supply field names, the values in the first row are used as the keys and that row is left out of the results.
import csv
with open("sales.csv", newline="") as f:
for row in csv.DictReader(f):
print(row["customer"], row["amount"])
Northwind 120.00
Smith, Jo 75.50
Blue Cafe 42.25
row["amount"] is easier to read than row[2], and it keeps working if a new column is added in front.
6. Writing dictionaries with DictWriter
csv.DictWriter goes the other way. Unlike DictReader, the documentation notes that its fieldnames argument is required, because it sets the column order. This script copies only the sales of 50 or more into a new file:
import csv
big = []
with open("sales.csv", newline="") as f:
for row in csv.DictReader(f):
if float(row["amount"]) >= 50:
big.append({"customer": row["customer"], "amount": row["amount"]})
with open("big_sales.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["customer", "amount"])
writer.writeheader()
writer.writerows(big)
The new file contains:
customer,amount
Northwind,120.00
"Smith, Jo",75.50
writeheader() writes the column names as the first row. If you pass a dictionary with a key that is not in fieldnames, the documentation says DictWriter raises a ValueError by default. Running it with an extra "note" key printed:
ValueError: dict contains fields not in fieldnames: 'note'
That error is protective: it stops data from silently going missing. If you really want extra keys ignored, the documentation lists extrasaction="ignore".
7. A checklist for CSV work
import csvand open files withnewline="".- Use
next(reader)orDictReaderto deal with the header row. - Convert numbers with
int()orfloat()before calculating. - Prefer
DictReaderandDictWriterwhen files have more than a few columns.
8. Key takeaways
- Do not split CSV lines on commas yourself; quoted values can contain commas.
- Open CSV files with
newline="", as the documentation recommends for both reading and writing. - csv.reader returns every value as a string, so convert numbers before math.
- DictReader uses the header row as keys, letting you read columns by name.
- DictWriter requires fieldnames and raises ValueError for unexpected keys unless told to ignore them.