Python CSV
Practical Python Practical Python Practical example

Python CSV Files

1Python CSV: overview

A CSV file stores a table as plain text — one row per line, values separated by commas — and Python's csv module reads and writes it correctly, including tricky cases such as commas inside quoted values.

GoalBy the end you can read CSV data with csv.reader and csv.DictReader, convert text columns to numbers, calculate totals, and write CSV files with csv.writer and csv.DictWriter.

Before this lesson: Python Dictionaries, Python File Handling

2Python CSV: diagram

sales.csvsales.csvproductqtyprice0Pen101.501Notebook43.252Bag124.00The csv module reads every value as a string: qty is "10", not 10
A CSV file is a table written as text: the first line holds the column names and each following line is one row. On disk this file is just the lines product,qty,price then Pen,10,1.50 and so on.

3Python CSV: explained step by step

CSV (comma-separated values) is the everyday format for tables. Spreadsheets export it, banks offer statements as CSV, and many public data sets are shared that way. A small CSV file looks like this:

product,qty,price
Pen,10,1.50
Notebook,4,3.25

Why not just split(",")?

Splitting each line on commas works until the data gets real. A value may contain a comma if it is wrapped in quotes ("Smith, Jane"), and quote characters inside values are doubled. The built-in csv module understands all of these rules, so let it do the parsing.

csv.reader: each row is a list

csv.reader() takes an open file — or anything that hands out lines — and gives you each row as a list of strings. Call next() on the reader once to take the header row before your loop.

Python
import csv
import io

data = io.StringIO('name,city\nAsha,Pune\n"Smith, Jane",Leeds\n')
reader = csv.reader(data)
header = next(reader)
print("Columns:", header)
for row in reader:
    print(row)

io.StringIO wraps a string so it behaves like an open file — useful for examples and tests. With a real file you would write open("people.csv", newline="") instead.

csv.DictReader: each row is a dict

DictReader uses the header row as keys, so every row becomes a dictionary such as {"product": "Pen", "qty": "10", "price": "1.50"}. row["price"] is much clearer than row[2], and your code keeps working if someone reorders the columns.

Everything is a string

The csv module never guesses types: "10" stays a string. Convert with int() or float() before doing maths — otherwise + either glues the text together or raises a TypeError.

Writing CSV

csv.writer(f) gives you writerow() for one row (a list) and writerows() for many. It adds quotes where needed and converts numbers to text for you. csv.DictWriter writes dicts instead — call writeheader() first to write the column names.

Always open CSV files with newline="". The csv module handles line endings itself, and without this setting some systems (notably Windows) show an empty line between every row.

Python
import csv

rows = [["day", "steps"], ["Mon", 6200], ["Tue", 8450]]
with open("steps.csv", "w", newline="") as f:
    csv.writer(f).writerows(rows)

with open("steps.csv", newline="") as f:
    for row in csv.reader(f):
        print(row)

When CSV files get large or you need grouping and statistics, the pandas library is the next step — but the csv module is always available and perfect for everyday scripts.

Quick reference: Python CSV

4Python CSV: syntax

import csv

with open("data.csv", newline="") as f:
    for row in csv.reader(f):           # row = list of strings
        ...

with open("data.csv", newline="") as f:
    for row in csv.DictReader(f):       # row = dict keyed by the header
        ...

with open("out.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["name", "score"])  # one row
    writer.writerows(rows)              # many rows

5Python CSV: run the example

Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.

Interactive example
import csv

with open("sales.csv", "w", newline="") as f:
    f.write("product,qty,price\n")
    f.write("Pen,10,1.50\n")
    f.write("Notebook,4,3.25\n")
    f.write("Bag,1,24.00\n")

grand_total = 0
with open("sales.csv", newline="") as f:
    for row in csv.DictReader(f):
        qty = int(row["qty"])
        price = float(row["price"])
        line_total = qty * price
        grand_total += line_total
        print(f"{row['product']:<10}{qty:>3} x {price:5.2f} = {line_total:6.2f}")

print(f"Grand total: {grand_total:.2f}")
Expected outputPen        10 x  1.50 =  15.00
Notebook    4 x  3.25 =  13.00
Bag         1 x 24.00 =  24.00
Grand total: 52.00

7Python CSV: how the example works

Hover or tap a step to highlight its lines in the example above.

  1. Line 1The csv module is part of the standard library.
  2. Line 3-7We create sales.csv first, because the browser's file system starts empty. On your own computer the file would usually already exist.
  3. Line 9A running total starts at 0.
  4. Line 10The file is opened for reading with newline="", as the csv module expects.
  5. Line 11DictReader reads the header line automatically, then gives each data row as a dict such as {'product': 'Pen', 'qty': '10', 'price': '1.50'}.
  6. Line 12-13The values are strings, so they are converted: int() for the quantity and float() for the price.
  7. Line 14-15The row's total is calculated and added to the grand total.
  8. Line 16Format codes line the columns up: <10 pads the name to 10 characters, >3 right-aligns the quantity, and .2f shows two decimals.
  9. Line 18After the loop, the grand total of all rows is printed: 15 + 13 + 24 = 52.

8Python CSV: common mistakes

Doing maths with the strings from a CSV

✗ Wrong

import csv
import io

data = io.StringIO("item,qty\napples,3\npears,5\n")
total = 0
for row in csv.DictReader(data):
    total += row["qty"]
TypeError: unsupported operand type(s) for +=: 'int' and 'str'

✓ Right

import csv
import io

data = io.StringIO("item,qty\napples,3\npears,5\n")
total = 0
for row in csv.DictReader(data):
    total += int(row["qty"])
print(total)

The csv module always returns strings. Convert with int() or float() before adding.

Splitting lines by hand

✗ Wrong

line = '"Smith, Jane",Leeds,42'
name, city, age = line.split(",")
ValueError: too many values to unpack (expected 3)

✓ Right

import csv

line = '"Smith, Jane",Leeds,42'
name, city, age = next(csv.reader([line]))
print(name, "|", city, "|", age)

split(",") also splits the comma inside the quoted name. Let csv.reader parse the line; it respects the quotes.

Treating the header row as data

✗ Wrong

import csv
import io

data = io.StringIO("name,score\nAsha,82\nBen,67\n")
total = 0
for row in csv.reader(data):
    total += int(row[1])
ValueError: invalid literal for int() with base 10: 'score'

✓ Right

import csv
import io

data = io.StringIO("name,score\nAsha,82\nBen,67\n")
reader = csv.reader(data)
next(reader)
total = 0
for row in reader:
    total += int(row[1])
print(total)

csv.reader returns the header line like any other row. Skip it with next(reader) before the loop, or use csv.DictReader, which handles the header for you.

9Python CSV: exercises

Write your answer, then press Check. The checks run in your browser.

1. Total a column

Write code Easy

Finish column_total(csv_text, column) so it returns the sum of all values in the named column, converted with float(). The reader is already set up for you.

Your code
import csv
import io

def column_total(csv_text, column):
    reader = csv.DictReader(io.StringIO(csv_text))
    total = 0
    # loop over the rows and add float(row[column]) to total
    return total

orders = "item,qty,price\nTea,2,4.50\nCake,1,3.25\n"
print(column_total(orders, "price"))

2. Predict the parsed rows

Predict the output Medium

The second line has a quoted value that contains a comma. Type exactly what the program prints.

Read this code
import csv
import io

text = 'name,tags\nAsha,"python,sql"\nBen,excel\n'
rows = list(csv.reader(io.StringIO(text)))
print(len(rows))
print(rows[1])
print(rows[2][1])

2 more exercises → 4 more examples

Finished this lesson?
Progress is saved in this browser — create a free account to keep it across devices.

Questions learners ask

Why does my CSV file have blank lines between the rows?

The file was opened without newline="". The csv writer already writes its own line endings, and on Windows the file object adds another one. Open CSV files with open(name, "w", newline="") for writing and newline="" for reading too.

Should I use the csv module or pandas?

The csv module is built in and ideal for reading, filtering and writing rows in small scripts. pandas loads the whole table into a DataFrame and is better for sorting, grouping, statistics and charts on larger data. Both work in the browser here.

How do I read a CSV file that uses semicolons or tabs?

Pass the separator to the reader: csv.reader(f, delimiter=";") or csv.reader(f, delimiter="\t"). DictReader and writer accept the same delimiter argument.

Further reading

10Next lesson

Up nextPython Regular Expressions (regex)A regular expression (regex) is a short pattern that describes the shape of some text — such as "three digits, a dash, …

Related:
Python DictionariesPython File HandlingWorking with JSON in PythonPandas Basics

← Working with JSON in Python · All Practical Python lessons · Practise in the IDE