Python Working with CSV Files

In the last lesson you learned Append Mode. That let you add new lines to the end of a file without erasing what was already there. It works great for plain text. But what if your data is a table? Picture a list of people, each with a name and an age. Now you need columns that line up. That is exactly the kind of data CSV was made for.

πŸ€” Why CSV Files?

Say you have a small list of people. Each person has a name and an age. You want to save it, share it, and open it again later. You could invent your own format with custom separators. But then you also have to write the code to read it back. That is extra work. And it breaks the moment one of your values has a comma in it.

CSV solves this for you. CSV stands for comma-separated values. It is a plain text format. Each line is a row. The values in that row are separated by commas. Think of it like a spreadsheet saved as simple text.

Here is what a CSV file looks like inside:

name,age
Alex,28
Riya,34
Arjun,21

The first line is the header. It names the columns. Every line after that is one row of data. Tools like Google Sheets, Excel, and most databases can open and save CSV. So it is a friendly way to move table data between programs.

Python gives you a built-in csv module for this. You do not install anything. It handles the tricky parts for you, like commas that sit inside a value.

πŸ“¦ Importing the csv Module

Before you do anything with CSV, you bring in the module. It ships with Python.

import csv

That one line is all you need. Now you have csv.writer and csv.reader ready to use.

✍️ Writing Rows with csv.writer

Let’s save our list of people to a file. We open a file for writing, create a writer, and hand it our rows.

import csv
people = [
["name", "age"],
["Alex", 28],
["Riya", 34],
["Arjun", 21],
]
with open("people.csv", "w", newline="") as file:
writer = csv.writer(file)
writer.writerows(people)
print("Saved people.csv")

Here is what each part does:

  • people is a list of rows. Each row is itself a list. The first row is the header.
  • open("people.csv", "w", newline="") opens the file for writing. The "w" means write mode. That creates the file or replaces it.
  • csv.writer(file) makes a writer object that knows how to turn lists into CSV lines.
  • writer.writerows(people) writes every row in one go. There is also writer.writerow() for a single row at a time.

When you run it, the program prints this:

Output

Saved people.csv

And the file people.csv now holds this:

Output

name,age
Alex,28
Riya,34
Arjun,21

That newline="" part is easy to forget. So let’s talk about why it matters.

Caution

When you open a file for writing CSV, always pass newline="". If you skip it on Windows, you can get a blank line between every row. Passing newline="" tells the csv module to handle line endings itself. That keeps your file clean on every system.

πŸ“– Reading Rows Back with csv.reader

Saving is only half the job. Now let’s read the file back and print each row. We open the file for reading and loop over it with a reader.

import csv
with open("people.csv", "r", newline="") as file:
reader = csv.reader(file)
for row in reader:
print(row)

Going through it line by line:

  • open("people.csv", "r", ...) opens the file in read mode with "r".
  • csv.reader(file) makes a reader that splits each line on commas for you.
  • The for loop walks through the file one row at a time.
  • Each row comes back as a list of strings.

Running it prints this:

Output

['name', 'age']
['Alex', '28']
['Riya', '34']
['Arjun', '21']

Notice one thing here. The age 28 comes back as the string '28', not the number 28. CSV is plain text. So everything you read is a string. If you need the age as a real number, you convert it yourself with int().

This small example reads the people and turns each age into a number. Then we can do math with it.

import csv
with open("people.csv", "r", newline="") as file:
reader = csv.reader(file)
next(reader) # skip the header row
for row in reader:
name = row[0]
age = int(row[1])
print(f"{name} will be {age + 1} next year")

The new piece is next(reader). It reads one row and throws it away. That skips the header, so we do not try to turn the word "age" into a number. Then for each person we pull the name and convert the age. And we print a friendly line.

Output

Alex will be 29 next year
Riya will be 35 next year
Arjun will be 22 next year

🏷️ Using Column Names with DictReader and DictWriter

Reading row[0] and row[1] works. But it is easy to mix up. Was age column 1 or column 2? The csv module has a nicer way. It can use the header names. So you read by name instead of by number.

csv.DictReader reads each row as a dictionary. The keys are the column names from the header.

import csv
with open("people.csv", "r", newline="") as file:
reader = csv.DictReader(file)
for row in reader:
print(f"{row['name']} is {row['age']} years old")

DictReader reads the first line as the header automatically. Then every row becomes a dictionary like {"name": "Alex", "age": "28"}. So row['name'] and row['age'] read by the column name. That is much clearer.

Output

Alex is 28 years old
Riya is 34 years old
Arjun is 21 years old

There is a matching csv.DictWriter for saving. You tell it the column names with fieldnames. You write the header once. Then you write each row as a dictionary.

import csv
people = [
{"name": "Alex", "age": 28},
{"name": "Riya", "age": 34},
{"name": "Arjun", "age": 21},
]
with open("people.csv", "w", newline="") as file:
writer = csv.DictWriter(file, fieldnames=["name", "age"])
writer.writeheader()
writer.writerows(people)
print("Saved with DictWriter")

Walking through the new parts:

  • fieldnames=["name", "age"] tells the writer which columns exist and in what order.
  • writer.writeheader() writes the header line name,age for you.
  • writer.writerows(people) writes each dictionary as a row, matching keys to columns.

Output

Saved with DictWriter

So when should you reach for which one? Here is a quick guide.

Tool Gives you Use when
csv.reader Each row as a list The file is simple or has no header
csv.DictReader Each row as a dictionary You want to read columns by name
csv.writer Writes lists as rows Your data is already lists
csv.DictWriter Writes dictionaries as rows Your data is dictionaries with named fields

⚠️ Common Mistakes

A few things trip people up the first time they work with CSV. Watch out for these.

  • Forgetting newline="" when opening the file. On Windows this can add a blank line between rows.
# ❌ Avoid: missing newline="" can give blank rows on Windows
with open("people.csv", "w") as file:
writer = csv.writer(file)
# βœ… Good: always pass newline="" for CSV
with open("people.csv", "w", newline="") as file:
writer = csv.writer(file)
  • Expecting numbers to come back as numbers. Everything read from CSV is a string. So convert when you need math.
# ❌ Avoid: this joins two strings, it does not add
total = row[1] + row[1]
# βœ… Good: convert to int first
total = int(row[1]) + int(row[1])
  • Splitting lines yourself with line.split(","). That breaks the moment a value contains a comma, like "Smith, Alex". The csv module handles quoted commas for you. So let it do the work.

βœ… Best Practices

A few simple habits will keep your CSV code clean and safe.

  • Always open CSV files inside a with block. It closes the file for you, even if something goes wrong.
  • Always pass newline="" when you write. It is essential there, since it stops the blank rows. Passing it when you read is harmless and is a fine habit too.
  • Use DictReader and DictWriter when your file has a header. Reading by column name is clearer and harder to break.
  • Convert strings to int or float right after you read them. Then the rest of your code works with real numbers.
  • Keep your header row consistent. The same column names in the same order make the file easy to read back.

🧩 What You’ve Learned

You can now move table data in and out of files with confidence.

  • βœ… CSV is a plain text format where each line is a row and commas separate the values.
  • βœ… The built-in csv module reads and writes CSV, no install needed.
  • βœ… csv.writer with writerow and writerows saves your rows to a file.
  • βœ… csv.reader reads rows back, and each value comes in as a string.
  • βœ… csv.DictReader and csv.DictWriter let you work with column names instead of number positions.
  • βœ… Always open CSV files for writing with newline="" to avoid blank lines.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does CSV stand for?

    Why: CSV means comma-separated values: each line is a row and commas separate the values in it.

  2. 2

    Why should you pass newline="" when opening a CSV file for writing?

    Why: Passing newline="" lets the csv module manage line endings, so you do not get an extra blank line between rows.

  3. 3

    When you read a row with csv.reader, what type are the values?

    Why: CSV is plain text, so every value comes back as a string and you convert it yourself when you need a number.

  4. 4

    What does csv.DictReader give you for each row?

    Why: DictReader uses the header line as keys, so each row is a dictionary you can read by column name.

πŸš€ What’s Next?

You now know how to handle table data. Next you will learn to save more nested data. Think of settings and lists inside lists. You will use a format the whole web speaks.

Working with JSON Files

Share & Connect