⚡ IT Wisdom Why don't sysadmins go outside? Because the sun has no man pages.
Skilled Practitioner
4249 XP 1751 to Expert
Units
Whetting Your Appetite — Why Python for Networking? Using the Python Interpreter An Informal Introduction to Python — Network Basics Control Flow — Making Decisions in Network Scripts Data Structures — Modeling Network Inventories Modules — Organizing Your Network Scripts Input and Output — Reading and Writing Network Data Errors and Exceptions — Building Reliable Network Scripts Classes — Modeling Network Devices as Objects Standard Library Part I — Tools Every Network Script Needs Standard Library Part II — Logging, Formatting, and Counting Virtual Environments and Packages — Isolating Your Dependencies Capstone — Build a Network Inventory Tool

Syntax Errors vs Runtime Exceptions

Syntax errors stop Python before your script even starts — a missing colon, an unclosed bracket. Python points at the line and refuses to run.

Runtime exceptions happen while the script is running — a file that does not exist, a dictionary missing a key, a value that cannot be converted to an integer. These are the errors that matter most in automation because they happen against real network data.


try / except — Handling Failures Gracefully

Wrap risky code in a try block. If it fails, the except block runs instead of crashing:

try:
    with open("devices.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("Error: device list file not found")

Without try/except, a missing file crashes the entire script. With it, the script handles the problem and continues.


Handling Multiple Exception Types

try:
    device = devices[hostname]
    vlan = int(device["vlan"])
except KeyError:
    print(f"Device {hostname} not found in inventory")
except ValueError:
    print(f"VLAN value is not a valid integer")

Each except clause catches a specific exception type. List the most specific ones first.


The else Clause

The else block runs only when no exception occurred:

try:
    with open("devices.txt") as f:
        devices = f.readlines()
except FileNotFoundError:
    print("File not found")
else:
    print(f"Loaded {len(devices)} devices successfully")

finally — Always Runs

finally runs whether an exception occurred or not. Use it to clean up — close connections, write a completion log, release resources:

try:
    process_devices()
except Exception as e:
    print(f"Error: {e}")
finally:
    print("Script complete")

Even if the script crashes halfway through, finally still runs.


Raising Exceptions

Raise an exception yourself when data fails a validation check:

def validate_vlan(vlan_id):
    if not 1 <= vlan_id <= 4094:
        raise ValueError(f"VLAN {vlan_id} is out of range (1-4094)")
    return True

Custom Exceptions

Create your own exception classes for domain-specific errors:

class InvalidIPAddress(Exception):
    pass

def validate_ip(ip):
    parts = ip.split(".")
    if len(parts) != 4:
        raise InvalidIPAddress(f"Invalid IP: {ip}")
    return True

Custom exceptions make your error messages specific and your code easier to debug.


Summary

  • try/except catches exceptions and keeps your script running
  • List the most specific exception type in each except clause
  • else runs only when no exception occurred — use it for the success path
  • finally always runs — use it for cleanup and completion logging
  • raise lets you validate data and fail early with a clear message
  • Custom exception classes make errors meaningful and debuggable