NetAuto Academy

Networking Data & Formats

Reading and Writing CSV Inventory Files

Beginner12 min read

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
🎓 Teach This Lesson

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.

devices.csv
hostname,ip,platform
SW1,10.10.10.1,cisco_ios
SW2,10.10.10.2,cisco_ios
SW3,10.10.10.3,cisco_ios

The 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

read_basic.py
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:

read_dict.py
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.

Quick checkConcept check
What's the key difference between csv.reader and csv.DictReader?
Quick checkPredict output
Given the devices.csv file shown above, what does 'devices = list(csv.DictReader(open('devices.csv')))' followed by 'print(devices[0])' print?

Writing CSV

Going the other direction, csv.DictWriter takes a list of dictionaries and writes them out as a CSV file, header row included:

write_report.py
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.)

Quick checkIdentify the correct code
Which line correctly writes the header row before writing the actual data rows, matching how DictWriter is meant to be used?

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:

csv_types.py
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 it

Every 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.

Quick checkScenario
A devices.csv file has a column 'vlan' with values like 10, 20, 30. After reading it with csv.DictReader, what type is device['vlan']?

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.