Networking Data & Formats
Reading and Writing CSV Inventory Files
What you'll learn
- What CSV is best suited for, compared to JSON and YAML
- The difference between csv.reader and csv.DictReader
- How to read a devices.csv file into the same list-of-dictionaries shape used all module
- How to write results back out to a CSV report with csv.DictWriter
- Why every value read from a CSV file is a string, even ones that look like numbers or booleans
Listen to a guided explanation of this lesson.
Spoken narration isn't supported in this browser.
CSV: the simplest structured format
CSV (comma-separated values) is exactly what it sounds like — a plain-text spreadsheet. Every line is a row; commas separate the columns. It's the format you get for free exporting from Excel or Google Sheets, and it's an excellent fit for a device inventory: a flat list where every device has the same fields.
hostname,ip,platform
SW1,10.10.10.1,cisco_ios
SW2,10.10.10.2,cisco_ios
SW3,10.10.10.3,cisco_iosThe first line is the header — the column names. Every line after it is one device, with values in the same order as the header.
CSV's simplicity is also its limit: it only really works for flat data. There's no natural way to represent something nested (a device with a list of VLANs, say) the way JSON or YAML can — which is exactly why the next lesson is about choosing between them.
Two ways to read a CSV file
import csv
with open("devices.csv") as f:
reader = csv.reader(f)
for row in reader:
print(row)csv.reader() gives you each row as a plain list — the first row printed will be ['hostname', 'ip', 'platform'], the header itself, since reader() doesn't know it's special.
That works, but every row comes back as a plain list, with no names attached to the values — you'd have to remember that row[0] is the hostname and row[1] is the IP. csv.DictReader solves exactly that, using the header row to build a dictionary for every device automatically:
import csv
with open("devices.csv") as f:
reader = csv.DictReader(f)
devices = list(reader)
for device in devices:
print(device["hostname"], device["ip"])DictReader reads the header row automatically and uses it as keys — device['hostname'] instead of row[0]. list(reader) turns the whole file into a list of dictionaries in one line: exactly the shape from 'Lists & Dictionaries for Network Data,' now loaded straight from a real file.
Writing CSV
Going the other direction, csv.DictWriter takes a list of dictionaries and writes them out as a CSV file, header row included:
import csv
results = [
{"hostname": "SW1", "status": "compliant"},
{"hostname": "SW2", "status": "NOT compliant"},
]
with open("report.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["hostname", "status"])
writer.writeheader()
writer.writerows(results)fieldnames tells DictWriter what the header row (and column order) should be. writeheader() writes that row first; writerows() writes one row per dictionary in results. (newline="" avoids an extra blank line between rows on some systems — a small, standard detail of using csv on Windows.)
Everything from CSV is a string
Here's a gotcha that should feel familiar — it's the exact one from "Variables, Data Types & Basic Operations," now showing up for a real reason:
import csv
with open("devices.csv") as f:
devices = list(csv.DictReader(f))
port = devices[0].get("ssh_port", "22")
print(port == 22) # False — port is the string "22", not the integer 22
print(int(port) == 22) # True — after converting itEvery value read from a CSV file is text, even a column that only ever contains digits. If you need to compare it against a real number, convert it first with int() or float() — otherwise "22" == 22 is False, for exactly the reason Lesson 2 of the Python module warned about.
This bites everyone once
A CSV column of port numbers, VLAN IDs, or a 'reachable' column of True/False text all come back as plain strings — never real integers or booleans — no matter how they look. Convert explicitly (int(), or a check like value == "True") before comparing or doing math with them.
Key takeaways
- CSV is a plain-text spreadsheet — ideal for flat, tabular data like a device inventory, but with no natural way to represent nested structure.
- csv.reader gives rows as plain lists; csv.DictReader uses the header row to give rows as named dictionaries — almost always the better default.
- list(csv.DictReader(f)) reads a whole CSV file into the same list-of-dictionaries shape used throughout this curriculum.
- csv.DictWriter, with writeheader() then writerows(), writes a list of dictionaries back out to a proper CSV file.
- Every value read from CSV is a string, even ones that look like numbers or booleans — convert explicitly before comparing or doing math with them.