Beginner Lab
Building a Device Inventory from CSV
Objective
Parse a CSV file into a list of dictionaries, then validate each row against required fields and a known-platform list, separating valid inventory from rejected rows with reasons.
Builds on Networking Data & Formats.
Prerequisites
- Comfortable with Python dictionaries and lists
- Familiar with reading CSV files (Reading and Writing CSV Inventory Files)
Scenario
The problem
"Reading and Writing CSV Inventory Files" taught you csv.DictReader on a clean file. Real inventory exports aren't clean -- a row is missing an IP address, another has a platform value nobody recognizes. Loading that straight into an inventory without checking it means your automation silently breaks three modules from now, on a device nobody remembers was ever wrong. This lab is the validation step no earlier lesson needed, because no earlier lesson's data was ever actually broken.
Starter data
hostname,ip_address,platform
SW1,10.10.10.11,cisco_ios
SW2,,arista_eos
SW3,10.10.10.13,junos_wrong
RTR1,10.10.10.21,cisco_iosFixed sample text written for this lab. Row 2 is missing an IP address; row 3 has a platform value that isn't real -- both deliberate, not typos to ignore.
Task
Write load_inventory(raw_csv) that:
- Parses the CSV using
csv.DictReader. - For each row, checks that
hostname,ip_address, andplatformare all present and non-empty. - Checks that
platform(when present) is one of{"cisco_ios", "arista_eos", "junos"}. - Returns two lists:
valid(rows that passed every check) andrejected(a dict per bad row containing the originalrowand a list oferrorsdescribing exactly what's wrong).
import csv
import io
RAW_CSV = """hostname,ip_address,platform
SW1,10.10.10.11,cisco_ios
SW2,,arista_eos
SW3,10.10.10.13,junos_wrong
RTR1,10.10.10.21,cisco_ios
"""
VALID_PLATFORMS = {"cisco_ios", "arista_eos", "junos"}
REQUIRED_FIELDS = ["hostname", "ip_address", "platform"]
def load_inventory(raw_csv):
# Your code here. csv.DictReader(io.StringIO(raw_csv)) gives you one
# dict per row -- check each REQUIRED_FIELDS entry, then check
# platform against VALID_PLATFORMS.
...
if __name__ == "__main__":
valid, rejected = load_inventory(RAW_CSV)
for row in valid:
print(row)
for r in rejected:
print(r)Copy into a local .py file and run with plain python3 -- csv and io are both standard library, no install needed.
Expected output
{'hostname': 'SW1', 'ip_address': '10.10.10.11', 'platform': 'cisco_ios'}
{'hostname': 'RTR1', 'ip_address': '10.10.10.21', 'platform': 'cisco_ios'}
{'row': {'hostname': 'SW2', 'ip_address': '', 'platform': 'arista_eos'}, 'errors': ['missing ip_address']}
{'row': {'hostname': 'SW3', 'ip_address': '10.10.10.13', 'platform': 'junos_wrong'}, 'errors': ["unknown platform 'junos_wrong'"]}Real, verified output from a working solution to this exact starter data.
Self-check only -- nothing here is submitted or graded. Compare against your own output manually.
Solution
Try the task yourself first -- the full solution and explanation stay hidden until you click above.
Key takeaways
- csv.DictReader turns rows into dicts -- but a dict with the right shape isn't the same as a dict with correct data.
- Separating valid rows from rejected ones (with a specific reason each) is more useful than either silently dropping bad rows or crashing on the first one.
- This is fixed, offline sample text -- not a real fleet export.
Related lessons
Done with this lesson?