NetAuto Academy

Advanced Python Automation for Network Engineers

Modules, Packages, and Organizing a Growing Script

Advanced11 min read

What you'll learn

  • The difference between a module and a package
  • How to split inventory-loading logic out of a capstone script into its own module
  • How imports between modules in the same package actually work
  • That this is purely organizational — no automation logic changes
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

A module is a file. A package is a folder of them.

Any .py file is already a module — every capstone script has been one. A package is a folder of modules that import from each other, with an __init__.py marking it as a package Python can import from.

the target layout
network_automation/
  __init__.py
  inventory.py      -- load_inventory()
  models.py          -- (Lesson 3)
  exceptions.py       -- (Lesson 3)
  connections.py       -- (Lesson 4)
  logging_config.py     -- (Lesson 5)
  automation.py          -- (Lessons 3-5)
  cli.py                  -- (Lesson 8)

Every file has exactly one job. inventory.py is the first one this lesson builds — everything else fills in over the rest of this module.

Quick checkConcept check
What's the actual difference between a Python module and a package?

Pulling inventory-loading out, unchanged

network_automation/inventory.py
import csv

def load_inventory(path):
  """The same devices.csv format used since Phase 2.6."""
  with open(path) as f:
      rows = list(csv.DictReader(f))
  return [row for row in rows if row.get("hostname")]

Exactly the same devices.csv-reading logic every capstone since Phase 2.6 has used -- moved into its own file, not rewritten.

using it from another file
from network_automation.inventory import load_inventory

devices = load_inventory("devices.csv")
print(devices)

import network_automation.inventory — real, verified import. A dotted path (package.module) followed by the specific function name.

output
[{'hostname': 'SW1', 'ip': '10.10.10.1', 'platform': 'cisco_ios'}, {'hostname': 'SW2', 'ip': '10.10.10.2', 'platform': 'cisco_ios'}, {'hostname': 'SW3', 'ip': '10.10.10.3', 'platform': 'cisco_ios'}, {'hostname': 'SW4', 'ip': '10.10.10.4', 'platform': 'cisco_ios'}, {'hostname': 'SW5', 'ip': '10.10.10.5', 'platform': 'cisco_ios'}]

Real, verified output against the same 5-device fleet from every prior capstone. Nothing about the logic changed -- only where it lives.

Quick checkIdentify the correct code
Given network_automation/inventory.py defines load_inventory(), which import correctly brings it into another file in the same package?

What didn't change

Zero logic changes in this lesson

load_inventory() reads the exact same devices.csv format, the exact same way, as every prior capstone. The only thing this lesson changed is where the function lives — from inline in a script to its own importable module. Every remaining lesson in this module adds exactly one more piece to this package, the same way.

Quick checkScenario
After this refactor, a second, completely unrelated script needs to load the same devices.csv format. What does it now take to reuse that logic?
Quick checkPredict output
load_inventory('devices.csv') is called against the same 5-row fleet used since Phase 2.6. What's returned?

Key takeaways

  • A module is one .py file (every capstone script has always been one); a package is a folder of modules that import from each other.
  • network_automation/inventory.py holds load_inventory() -- the exact same devices.csv-reading logic from every prior capstone, moved, not rewritten.
  • from package.module import name is the standard import shape for pulling a function from another file in the same package.
  • This lesson changed zero automation logic -- purely organizational, the first mechanical step every remaining lesson builds on.