runtime
97 / 250
lesson 97 CSV JSON & JSONL · intermediate

Write CSV files with a header

`csv.DictWriter` writes a header and one line per dictionary, quoting values that contain commas or quotes, so any spreadsheet or CSV reader can read the file back.

You'll be able to
  • Create a csv.DictWriter with the column order, write the header once and then the rows
  • Explain what newline="" prevents and how values with commas and quotes are written
  • Choose columns from wider rows with extrasaction="ignore", and read one CSV while writing another
The idea

Writing CSV by gluing strings breaks the moment a value contains a comma. csv.DictWriter(file, fieldnames=[...]) takes the column order once, writeheader() writes the header line, and writerow(row) (or writerows(rows)) writes each dictionary's values in that order, quoting any value that contains a comma, a quote or a line break.

Open the file with newline="". The csv module ends each line with \r\n itself, as the CSV standard asks; without newline="", Windows would turn that \n into another \r\n and the file would show a blank line between rows.

Run each example to see what it prints. Running examples doesn't count toward progress.

example-1.py · A header, two rows and a quoted comma
import csv

rows = [
    {"sku": "HOM-52782", "name": "Deluxe Pillow", "price": 47.99},
    {"sku": "BOO-58412", "name": "Handbook, Nordic edition", "price": 15.99},
]
with open("products.csv", "w", encoding="utf-8", newline="") as out:
    writer = csv.DictWriter(out, fieldnames=["sku", "name", "price"])
    writer.writeheader()
    writer.writerows(rows)

with open("products.csv", encoding="utf-8", newline="") as source:
    print(repr(source.read()))

DictWriter is strict about extra keys. Rows from another source often carry more fields than the export should have, and writing one raises an error rather than silently dropping data.

example-2.py · A field that isn't a column
import csv

with open("export.csv", "w", encoding="utf-8", newline="") as out:
    writer = csv.DictWriter(out, fieldnames=["order_id", "total"])
    writer.writeheader()
    writer.writerow({"order_id": "O100043", "total": 12.93, "status": "delivered"})
example-3.py · Copy chosen columns into a new file
import csv

def export_columns(src, dest, columns):
    count = 0
    with open(src, encoding="utf-8", newline="") as source, open(dest, "w", encoding="utf-8", newline="") as out:
        writer = csv.DictWriter(out, fieldnames=columns, extrasaction="ignore")
        writer.writeheader()
        for row in csv.DictReader(source):
            writer.writerow(row)
            count += 1
    return count

with open("customers.csv", "w", encoding="utf-8", newline="") as out:
    out.write("customer_id,first_name,last_name,email,city,state\n")
    out.write("C00164,Isaac,Sato,isaac.sato62@gmail.com,New York,NY\n")
    out.write("C00800,Samuel,Mensah,samuel_mensah@yahoo.com,Miami,FL\n")

print(export_columns("customers.csv", "mailing.csv", ["email", "first_name"]))
with open("mailing.csv", encoding="utf-8", newline="") as source:
    for row in csv.reader(source):
        print(row)

When to use it: any time you hand data to a spreadsheet, another team or another program. Mistakes to avoid: writing the header inside the loop (once per row), opening without newline="", and building lines with ",".join(...), which breaks on the first value that contains a comma.

Review
  • csv.DictWriter(out, fieldnames=[...]), then writeheader() once, then writerow/writerows.
  • Open with newline=""; the module writes \r\n and quotes values that need it.
  • Extra keys raise ValueError unless extrasaction="ignore"; missing keys become empty values.
  • Next: JSON, for data with nesting, lists and real types.
Practise this

Loading your progress…

To master this lesson, solve both challenges without hints or the answer, and pass the concept check.

Write CSV files with a header — CSV JSON & JSONL · Runtime