04 / FILES AND FORMATS · LESSON 14

CSV without broken columns

Read structured records and produce a correctly quoted CSV report.

14 min · learn at your pace

Let the CSV parser do its job

CSV is more than text separated by commas. A quoted field can contain a comma, a quote, or a newline. Splitting every line on commas breaks those records. csv.DictReader uses the header row as dictionary keys and handles quoting for you.

Values read from CSV are strings. Convert numeric fields with int() before comparing them. The text "false" is a nonempty string, so bool("false") is true. Compare to the documented spelling or use an explicit conversion rule.

Write a clear output contract

csv.DictWriter takes a fieldname list that defines column order. Call writeheader(), then write records with those fields. Open CSV files with newline="" so the CSV library controls line endings, and use UTF-8 for names beyond ASCII.

A with block closes the file even if an error occurs. Write reports using mode "w" to replace old results. The owner field in this lesson includes a comma; a correct round trip keeps it in one cell. Checks read your output as CSV rather than judging its raw line-ending style.

Try an example.py
import csv
with open("assets/servers.csv", newline="", encoding="utf-8") as source:
    for row in csv.DictReader(source):
        print(row["name"], int(row["memory_gb"]))
YOUR TURN

Put it into practice.

Create output/eligible.csv from assets/servers.csv. Include active ("true") rows with memory_gb at least 16, sorted by name. Write the columns name,memory_gb,owner in that order and preserve owner text, including commas. Repeated runs must replace the report.

See an explained solution
One way to solve it.py
import csv
from pathlib import Path
with open("assets/servers.csv", newline="", encoding="utf-8") as source:
    rows = [row for row in csv.DictReader(source) if row["active"] == "true" and int(row["memory_gb"]) >= 16]
rows.sort(key=lambda row: row["name"])
Path("output").mkdir(exist_ok=True)
with open("output/eligible.csv", "w", newline="", encoding="utf-8") as target:
    writer = csv.DictWriter(target, fieldnames=["name", "memory_gb", "owner"])
    writer.writeheader()
    for row in rows:
        writer.writerow({key: row[key] for key in writer.fieldnames})

The parser handles quoted values, the filter compares integers, and DictWriter controls the output schema. Replacing the file makes the report safe to rerun.