Skip to main content
Your first session is free. Claim mine
PacketMentor logo
Open menu
Home
Training
CCNA Library (74)
Browse all CCNA topics →
Network (13)
Device Operations (5)
Network Access (12)
Wireless (6)
IP Connectivity (10)
IP Services (11)
Security (10)
Automation (7)
CCNP Library (15)
LabsPricing
Contact 📞 +1 (860) 556-3010 Book a Call
← All topics
Automation & Programmability Foundational

Python for Network Engineers

Why Python is the de-facto language for network automation, plus the four libraries you'll actually use — Netmiko (SSH), NAPALM (vendor-agnostic), Nornir (parallel runner), and requests (REST APIs).

TL;DR
  • Python is the default scripting language for network automation. Easy syntax, huge ecosystem, runs everywhere.
  • Four libraries cover 90% of jobs: Netmiko (SSH to devices), NAPALM (vendor-agnostic ops), Nornir (parallel execution), requests (REST APIs).
  • Start with a script that loops over a device list and runs `show ip int brief` on each. Build from there.

Mental model

Network engineering used to be SSH, command, screen-scrape, repeat. That doesn’t scale past a handful of devices. Python is the language of choice for replacing that workflow with code:

  • Easy syntax — closer to English than other languages
  • Massive ecosystem of network libraries
  • Runs on Windows, macOS, Linux, your laptop, a server, in CI
  • Same skills transfer to other automation (servers, cloud, security)

You don’t need to be a software engineer. You need to write small, useful scripts. 50 lines that update a thousand switches’ SNMP community string in 30 seconds is real Python value.

The four libraries you’ll actually use

LibraryJobWhen to use
NetmikoSSH to network devices, send commandsQuick scripts, multi-vendor SSH
NAPALMVendor-agnostic operations (get facts, push config, rollback)When you need cross-vendor compatibility
NornirParallel runner with built-in inventoryRunning anything against many devices fast
requestsHTTP / REST APIsModern APIs (Meraki, DNA Center, RESTCONF)

Plus paramiko (lower-level SSH — Netmiko uses it under the hood) and ncclient (NETCONF — see NETCONF & YANG topic).

Hello world — read interface status from one device

from netmiko import ConnectHandler

device = {
    "device_type": "cisco_ios",
    "host": "10.0.0.1",
    "username": "admin",
    "password": "cisco123",
}

with ConnectHandler(**device) as conn:
    output = conn.send_command("show ip interface brief")
    print(output)

That’s a working network-automation script. Eight lines. Replace with send_config_set(["interface gi0/0", "description WAN-link"]) to push config.

Loop over many devices

from netmiko import ConnectHandler

devices = [
    {"device_type": "cisco_ios", "host": "10.0.0.1", "username": "admin", "password": "x"},
    {"device_type": "cisco_ios", "host": "10.0.0.2", "username": "admin", "password": "x"},
    {"device_type": "cisco_ios", "host": "10.0.0.3", "username": "admin", "password": "x"},
]

for dev in devices:
    with ConnectHandler(**dev) as conn:
        print(f"--- {dev['host']} ---")
        print(conn.send_command("show version | i Cisco IOS"))

Run it: takes ~30 seconds for 100 devices in serial. Use Nornir or concurrent.futures to parallelize down to ~3 seconds.

NAPALM — vendor-agnostic

NAPALM gives you a consistent API across Cisco IOS, NX-OS, Juniper, Arista, and others. Same code, different platform:

from napalm import get_network_driver

driver = get_network_driver("ios")
device = driver(hostname="10.0.0.1", username="admin", password="x")
device.open()

facts = device.get_facts()
print(facts["model"], facts["os_version"])

interfaces = device.get_interfaces()
for name, data in interfaces.items():
    print(f"{name}: up={data['is_up']}")

device.close()

Switch "ios" to "junos" and the script works against a Juniper router. NAPALM normalizes the differences.

REST API — Cisco Meraki example

import requests

api_key = "your-api-key"
org_id = "your-org-id"

resp = requests.get(
    f"https://api.meraki.com/api/v1/organizations/{org_id}/networks",
    headers={"X-Cisco-Meraki-API-Key": api_key},
)
networks = resp.json()
for net in networks:
    print(net["id"], net["name"])

Modern Cisco platforms (Meraki, DNA Center, ISE, Webex) all expose REST APIs. See REST APIs for Network Engineers for the deeper dive.

Parallel execution with Nornir

Nornir is Python-native parallelism + inventory + plugin system. Same idea as Ansible but feels native (no YAML files for tasks).

from nornir import InitNornir
from nornir_netmiko import netmiko_send_command

nr = InitNornir(config_file="config.yaml")
result = nr.run(task=netmiko_send_command, command_string="show ip int brief")

for host, output in result.items():
    print(f"--- {host} ---")
    print(output[0].result)

InitNornir reads hosts.yaml and groups.yaml (Ansible-style inventory). The .run() call executes in parallel — default 20 workers, configurable.

Practical patterns you’ll use

1. Bulk config audit

for dev in inventory:
    output = ssh.send_command("show running-config | i ^username")
    if "admin" not in output:
        print(f"ALERT: {dev['host']} missing admin user")

2. Backup all configs to git

for dev in inventory:
    config = ssh.send_command("show running-config")
    open(f"backups/{dev['host']}.cfg", "w").write(config)
# then: git add . && git commit -m "Daily backup"

3. Templated config push

from jinja2 import Template

template = Template("""
interface {{ interface }}
 description {{ description }}
 ip address {{ ip }} {{ mask }}
 no shutdown
""")

config = template.render(
    interface="Gi0/0",
    description="WAN to ISP-A",
    ip="203.0.113.1",
    mask="255.255.255.252",
).splitlines()

ssh.send_config_set(config)

Jinja2 for templates is universal — Ansible uses the same templating engine.

Common mistakes

  1. Hardcoding credentials. Use environment variables or a secrets file you exclude from git:
import os
password = os.environ["NETWORK_PASSWORD"]
  1. No error handling. SSH connections fail constantly (timeouts, wrong creds, device down). Wrap in try/except:
from netmiko.exceptions import NetMikoTimeoutException

try:
    with ConnectHandler(**dev) as conn:
        ...
except NetMikoTimeoutException:
    print(f"Could not reach {dev['host']}")
  1. Pushing config without a backup or rollback plan. Backup the running config first, push the change, verify the result, restore from backup if needed.

  2. Running on all 500 devices on the first try. Start with one. Then ten. Then all of them. Mistakes at scale are expensive.

  3. Mixing Python 2 and Python 3. Python 2 is end-of-life since 2020. Use Python 3.10+ for modern syntax, type hints, and library compatibility.

  4. Not using virtual environments. pip install system-wide pollutes your machine. Always:

python3 -m venv venv
source venv/bin/activate
pip install netmiko napalm nornir requests
  1. Treating output as freeform text forever. Plain send_command() returns text you have to regex. Use NAPALM’s get_interfaces() or device APIs that return structured JSON when possible.

Lab to try tonight

  1. Spin up a Cisco DevNet sandbox or two Cisco devices in CML.
  2. pip install netmiko in a virtualenv.
  3. Write a script that SSHes to one device and prints show version. Get it working with one device.
  4. Add a second device. Loop over both.
  5. Send a config change (e.g. description test on a loopback). Verify it stuck via SSH.
  6. Add try/except for connection failures.
  7. Switch to NAPALM and use get_facts(). Compare vs the raw text output.
  8. Bonus: use Jinja2 to template a multi-line config from a dictionary of variables. Push it.

Cheat strip

LibraryWhat it does
NetmikoSSH wrapper for multi-vendor — start here
NAPALMVendor-agnostic ops — same code, different platforms
NornirInventory + parallel runner — pure Python alternative to Ansible
requestsHTTP / REST APIs
ncclientNETCONF (XML over SSH)
paramikoLow-level SSH (used by Netmiko under the hood)
Jinja2Config templating
VirtualenvIsolated Python environment — always use one
Environment varsFor secrets — never hardcode passwords
try/exceptNetwork operations fail. Wrap them.
Master this on a real network

Want this drilled into reflex?

1:1 weekly sessions, live feedback on your labs, and US interview prep — built around the CCNA® exam blueprint. Free first session. No card on file until you decide.

Claim my free session →

One topic per email, every fortnight

VLANs, OSPF, ACLs, subnetting, automation — written like this. Unsubscribe in one click.

We respect your inbox. One email per week, max. Unsubscribe any time.

Start typing — or browse popular topics below.

↑↓ navigate open Searches topics · labs · programs · pages