Modules, Packages, and the Capstone

The last step from scripts to software: organizing your functions into modules and packages that import like the libraries do. Then the capstone - assembling everything from all ten lessons into netaudit, a small, graded, genuinely useful audit package.

TL;DR - only got 10 minutes? This is the lesson. Hit to have it read to you.
  • Any .py file is a module: netparse.py becomes import netparse, and netparse.find_serial(...) just works - your code imports like the stdlib.
  • Top-level code runs ON IMPORT. Guard anything script-like with if __name__ == "__main__": - the file then works both as an import and as a command.
  • A package is a directory of modules with an __init__.py: netaudit/parsers.py imports as from netaudit.parsers import find_serial.
  • The layout you've seen in every lab - package + tests/ beside it - IS the professional convention. You've been absorbing it all course.
  • Capstone: netaudit assembles the whole course - regex parsers (L5), audit logic with loops and sets (L3-4), report rendering with f-strings (L1, L6).
  • After this lesson you have every prerequisite for the flagship course, where these parsers point at LIVE devices over SSH instead of saved files.
  • Prove it: download the capstone, set up a venv, and make the grader green on your own machine - your one local lab and the bridge to the paid course.
In this lesson you will:
  • Turn a .py file into an importable module
  • Guard script behavior with if __name__ == "__main__"
  • Organize modules into a package with __init__.py
  • Build the netaudit capstone - parsers, audit logic, and reporting
  • Know exactly what the flagship course builds on top of this

Any file is a module

You’ve imported other people’s code for nine lessons. The mechanism was never special - import x looks for x.py, and yours qualifies:

# netparse.py
import re

def find_serial(text):
    m = re.search(r"Processor board ID (\S+)", text)
    return m.group(1) if m else None
>>> import netparse
>>> netparse.find_serial("Processor board ID FOC2217A0AB")
'FOC2217A0AB'

That’s it. The file’s name becomes the namespace, its functions become the API, and the docstrings you’ve been writing since Lesson 6 become its help() output. from netparse import find_serial imports the one name when that reads better.

name: import-safe and runnable

One subtlety with teeth: everything at a module’s top level runs at import time. If netparse.py ends with test calls and prints, every script that imports it triggers them. The guard:

# netparse.py (bottom of file)
if __name__ == "__main__":
    # runs ONLY when executed directly: python3 netparse.py
    sample = "Processor board ID FOC2217A0AB"
    print(find_serial(sample))

Python sets __name__ to "__main__" when a file is executed directly, and to the module’s own name when it’s imported. One file, two lives: a library to importers, a quick self-demo from the command line. You’ll find this guard at the bottom of practically every serious Python file on GitHub - now you can read it.

Packages: modules, organized

When one file gets crowded, a package is a directory of modules:

netaudit/
├── __init__.py        # marks the directory as a package (can be empty)
├── parsers.py         # extraction: text in, facts out
├── audit.py           # judgment: facts in, findings out
└── report.py          # rendering: findings in, humans informed
from netaudit.parsers import find_serial
from netaudit.audit import missing_descriptions
from netaudit.report import render

Notice the split isn’t alphabetical - it’s by responsibility, the composition discipline from Lesson 6 scaled up to files. Parsing doesn’t know about reporting; reporting doesn’t know about regex. When a parser breaks on a new platform’s output, you know which file to open before you’ve read a line of code.

netaudit - data flows left to right, cli.py drives
Rendering diagram…
View diagram source - it's just text (Mermaid). Diagrams-as-code is how modern network docs work; the flagship course has a free module on it.
flowchart LR
  CFG[/"config file"/] --> P["parsers.py<br/>text → facts"]
  P --> A["audit.py<br/>facts → findings"]
  A --> R["report.py<br/>findings → humans"]
  CLI["cli.py<br/>__main__ guard"] -.imports.-> P
  CLI -.imports.-> A
  CLI -.imports.-> R

(That figure, like every diagram in this course, is a Mermaid diagram - plain text that lives in Git next to the code, no Visio license required. The flagship course includes a module on documenting entire networks this way.)

The capstone: netaudit

The final lab assembles the course. You implement five pieces across the three modules - every one of them a skill you already have:

Piece Module Built from
find_interfaces() parsers L3 accumulator + .startswith()
find_serial() parsers L5 regex + the None contract
missing_descriptions() audit L3’s challenge, now packaged
vlan_drift() audit L4 set difference, both directions
render() report L1/L6 f-strings + truthiness

A working cli.py ships with the lab - once your functions pass, it audits real config files from the command line via the __main__ guard. You don’t write it; you read it and recognize every line.

Your code becomes a package
Try it yourself (Python runs in your browser)
Output appears here. First run downloads the Python runtime (~10 MB), so give it a few seconds.

The capstone - your one local lab

Every other lab in this course runs in your browser. This one, you run on your own machine, on purpose: a real package, a real virtual environment, a real command-line tool. It is also your bridge to the paid course, where every lab is local. Here is the whole loop.

1. Get the starter. Download netaudit-capstone.zip and unzip it. Inside is the netaudit/ package skeleton, a sample config, a working cli.py, and the grader.

2. Set up once.

cd netaudit-capstone
python3 -m venv .venv && source .venv/bin/activate   # macOS / Linux
# .venv\Scripts\activate                             # Windows PowerShell
pip install pytest

3. Fill in the five functions across parsers.py, audit.py, and report.py, then grade yourself - red until the work is done, green when it is:

pytest -q

4. Run the tool you earned. When all five pass:

python3 cli.py sample-configs/acc-sw03.cfg

That is your package, doing a real audit, from the command line. Reference solutions ship in solutions/ - read them only after an honest attempt.

You’re done - here’s what you’re ready for

Ten lessons ago you set up a venv; today you shipped a package. You can read files, parse with string methods and regex, model devices as classes, detect drift with sets, survive bad input, and organize it all so the next person can use it. That is, precisely, the prerequisite list for AI-Assisted Network Automation - the flagship course - where this exact skill set turns toward live devices: Netmiko sessions instead of saved files, structured parsing with TextFSM instead of hand-rolled regex, config generation with Jinja2 templates, multivendor fleets through Nornir, and a CI/CD capstone that takes a change from Git commit to validated deployment. Same bones. Real switches. See the course page for the curriculum and presale.

Check your understanding

You import netparse and a demo report immediately prints, uninvited. What's wrong with netparse.py?

1 / 3

Summary

Modules are just files - your netparse.py imports exactly like the stdlib, with the __main__ guard keeping import-time side effects out and command-line convenience in. Packages organize modules by responsibility behind an __init__.py, and the parse/judge/render split of the capstone is real tooling architecture at learning scale. The capstone itself is the course in one artifact: every lesson’s skill, composed. What comes next - live SSH, structured parsing, templating, fleet-scale orchestration - is the flagship course’s job. You’ve built the foundation it stands on.