If you've spent years typing commands into network devices one at a time, you know the problems: a simple configuration change across 50 routers means 50 separate SSH sessions, 50 opportunities for typos, and hours of your day gone. When something breaks at 2 AM, you're left manually checking each device to isolate the issue.
Python libraries for network engineers solve this by handling repetitive, error-prone work. They allow you to programmatically connect to devices, parse command outputs, validate configurations, and execute changes consistently and at scale.
This guide covers ten essential Python libraries that will save you and your team countless hours, cut down on errors, and make your work life way easier. We'll explain what each library does, why it's useful, where it fits in your workflow, and give you practical examples, focusing on Cisco environments but noting multi-vendor support where applicable.
Table of contents
You don't need to learn all ten libraries at once. Here's a sensible learning path:
Beginner Path (Get the Fundamentals):
Intermediate Path (Expand and Scale):
Advanced Path (Build Production-Ready Workflows):
This progression makes sense because it builds on itself. Netmiko teaches you SSH basics, NAPALM adds vendor abstraction, Nornir gives you orchestration, and the advanced libraries let you build enterprise-scale workflows.
Nornir is a pure-Python automation framework. It helps manage your inventory, connect to devices, and run tasks in parallel. It keeps you in control of your Python code.
How it works:
Why it's great:
Where to use it: Perfect for tasks like backing up configs, running compliance checks, deploying standard configs ("golden configs"), and building pre-/post-change validation pipelines. Understanding common network automation challenges and mistakes helps you design better Nornir workflows from the start.
Example – Collect CDP neighbors from Cisco devices and save to a CSV:
# pip install nornir nornir-netmiko
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
import csv
nr = InitNornir(config_file="config.yaml") # uses inventory/{hosts,groups}.yaml
def cdp(task):
r = task.run(netmiko_send_command, command_string="show cdp neighbors detail", use_textfsm=True)
task.host["cdp"] = r.result # list[dict]
result = nr.run(task=cdp)
print_result(result)
with open("cdp_neighbors.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["host","local_port","neighbor","neighbor_port","platform"])
writer.writeheader()
for host, tasks in result.items():
for row in tasks[0].result:
writer.writerow({
"host": host,
"local_port": row.get("local_port"),
"neighbor": row.get("destination_host"),
"neighbor_port": row.get("remote_port"),
"platform": row.get("platform"),
})
Multi-vendor Support: Nornir works with any platform supported by its task plugins like Netmiko, Scrapli, NAPALM, or HTTPX, covering Cisco IOS-XE, NX-OS, IOS-XR, Arista EOS, Juniper Junos, FortiOS, PAN-OS, and many more. Inventory from NetBox or Ansible enables a single orchestrator over heterogeneous fleets.
Both are powerful tools that orchestrate tasks across multiple devices, but they have different approaches.
Use Nornir when: You want full Python control, need to integrate with other Python libraries, need complex post-processing of results, and your team is comfortable with Python.
Use Ansible when: Your team prefers declarative YAML, you need to automate a broader range of IT tasks, you want to leverage a vast library of ready-made modules, or you need enterprise features like a web UI and RBAC (available in AWX/AAP).
Can You Use Both? Yes. Many teams use Ansible for server/cloud automation and Nornir for network-specific workflows. You can even call Nornir scripts from Ansible playbooks.
|
Nornir |
Ansible |
---|---|---|
Language |
Pure Python |
YAML + Python (modules) |
Learning Curve |
Steeper (Python required) |
Gentler (YAML declarative) |
Flexibility |
Very high |
Moderate (module-dependent) |
Network Focus |
Yes (built for it) |
Good (general IT tool) |
Result Processing |
Programmatic (Python) |
Limited (filters, callbacks) |
Inventory |
Python/YAML/NetBox |
INI/YAML/dynamic sources |
Speed |
Fast (multithreading) |
Moderate (SSH overhead) |
Debugging |
Python debugger |
Verbose mode, callbacks |
NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is a Python library that gives you a standard, unified way to get device state and manage configurations across different network OSes.
How it works:
Why it's great:
Where to use it: Perfect for getting baseline configurations, managing standard changes reliably across various platforms.
Example – Get facts from a Cisco IOS-XE device and push a configuration change:
# pip install napalm
from napalm import get_driver
driver = get_driver("ios")
dev = driver(hostname="10.0.0.10", username="admin", password="admin", optional_args={"secret": "admin"})
dev.open()
facts = dev.get_facts()
print(facts["hostname"], facts["os_version"])
candidate_cfg = """
interface Loopback100
description added-by-napalm
ip address 192.0.2.100 255.255.255.255
"""
dev.load_merge_candidate(config=candidate_cfg)
print(dev.compare_config()) # show diff
dev.commit_config()
dev.close()
Multi-vendor Support: Has solid drivers for Cisco (IOS, IOS-XE, NX-OS, IOS-XR), Juniper (Junos), and Arista EOS. Community drivers exist for others too.
Netmiko is a device-aware layer built on Paramiko that simplifies CLI automation by understanding network device prompts, handling command paging, and managing privilege levels. Learning Netmiko is the best place to start with Python network automation. If you're new to Python-based network automation, learning how to leverage Netmiko for network automation is the best place to start.
How it works:
Why it's great:
Where to use it: Quick scripts, brownfield devices without API/NETCONF, or when you want deterministic CLI transactions.
Example – Configure a description on IOS-XE and save
# pip install netmiko
from netmiko import ConnectHandler
dev = {
"device_type": "cisco_ios",
"host": "10.0.0.10",
"username": "admin",
"password": "admin",
"secret": "admin",
}
with ConnectHandler(**dev) as conn:
conn.enable()
output = conn.send_config_set([
"interface GigabitEthernet1",
"description Uplink-to-ISP",
])
print(output)
print(conn.save_config()) # write memory on supported platforms
Multi-vendor Support: Built-in drivers for Cisco, Arista, and Juniper. NETCONF support works on any vendor implementing the standard and relevant YANG models.
Scrapli is a modern, high-performance Python library for talking to network devices via CLI, NETCONF, or RESTCONF. It offers both synchronous and asynchronous (asyncio) support, making it super fast for interacting with many devices at once.
How it works:
Why it's great:
Where to use it: Perfect for grabbing lots of data quickly, doing NETCONF/YANG operations, and any automation that benefits from asyncio's speed.
Example – Async CLI Get (show ip interface brief) on Cisco devices:
import asyncio
from scrapli.driver.core import AsyncIOSXEDriver, AsyncNXOSDriver
devices = [
(AsyncIOSXEDriver, {"host": "10.0.0.11", "auth_username": "admin", "auth_password": "admin", "auth_strict_key": False}),
(AsyncNXOSDriver, {"host": "10.0.0.12", "auth_username": "admin", "auth_password": "admin", "auth_strict_key": False}),
]
async def run(cls, params):
async with cls(**params) as conn:
r = await conn.send_command("show ip interface brief")
return params["host"], r.result.splitlines()[0]
async def main():
results = await asyncio.gather(*(run(cls, p) for cls, p in devices))
for host, first_line in results:
print(host, first_line)
asyncio.run(main())
Example – NETCONF get-config on Cisco IOS-XE:
# pip install scrapli scrapli-netconf
from scrapli_netconf.driver import NetconfDriver
with NetconfDriver(host="10.0.0.11", auth_username="admin", auth_password="admin", auth_strict_key=False) as nc:
reply = nc.get(filter_='<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>')
print(reply.result) # NETCONF XML payload
Multi-vendor Support: Has built-in drivers for Cisco, Arista, and Juniper. NETCONF support works on any vendor that implements the standard and relevant YANG models.
Network engineers often ask which Python library to use for CLI automation. Here's a practical comparison:
|
Netmiko |
NAPALM |
Scrapli |
---|---|---|---|
Async Support |
No |
No |
Yes |
Config Diff |
No |
Yes |
Via plugins |
Config Rollback |
No |
Yes |
Via plugins |
Multi-vendor Abstraction |
Partial |
Yes |
Partial |
TextFSM Integration |
Built-in |
No |
Via plugins |
NETCONF Support |
No |
No |
Yes (scrapli-netconf) |
Learning Curve |
Easy |
Moderate |
Moderate |
Community Size |
Large |
Large |
Growing |
pyATS is Cisco’s extensive network testing framework, which includes Genie, a library with a vast collection of accurate, structured parsers for Cisco CLI outputs.
How it works:
Why it's great:
Where to use it: Pre-/post-change validation, continuous compliance, and "learn and compare" workflows. For advanced use cases, pyATS can power network digital twins for testing and validation before production changes.
Example – Parse BGP summary on IOS-XE
# pip install pyats[full] genie
from genie.conf.base import Device
dev = Device(name="edge1", os="iosxe")
dev.custom.abstraction = {"order": ["os"]}
sample = """
BGP router identifier 192.0.2.1, local AS number 65001
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
203.0.113.2 4 65002 1200 1188 9 0 0 1d02h 42
"""
parsed = dev.parse("show ip bgp summary", output=sample)
neighbor = list(parsed["vrf"]["default"]["neighbor"].keys())[0]
print(neighbor, parsed["vrf"]["default"]["neighbor"][neighbor]["address_family"]["ipv4 unicast"]["prefix_received"])
Multi-vendor Support: Best and most comprehensive coverage for Cisco IOS-XE, NX-OS, IOS-XR, and ASA. Parsers also exist for Arista and Juniper but are smaller and community-supported. For unsupported commands or vendors, you can combine pyATS with TextFSM.
TextFSM is a powerful state machine and regex-based templating engine for extracting specific fields from unstructured CLI output.
How it works:
Why it's great:
Where to use it: Writing custom parsers for rare or proprietary commands, handling interim parsing needs during migrations, and parsing vendor-specific outputs other libraries don't cover.
Example – Parse show cdp neighbors detail
# pip install textfsm
import textfsm, io
template = io.StringIO(r"""
Value LocalPort (\S+)
Value Neighbor (\S+)
Value RemotePort (.+?)
Value Platform (.+?)
Start
^Device ID:\s+${Neighbor}
^Interface:\s+${LocalPort},\s+Port ID \(outgoing port\):\s+${RemotePort}
^Platform:\s+${Platform} -> Record
""")
sample = """
Device ID: dist1
Interface: GigabitEthernet1, Port ID (outgoing port): Ethernet1/1
Platform: cisco WS-C3850-48P, Capabilities: Switch IGMP
"""
parser = textfsm.TextFSM(template)
rows = parser.ParseText(sample)
records = [dict(zip(parser.header, r)) for r in rows]
print(records[0]["Neighbor"], records[0]["RemotePort"])
Multi-vendor Support: Templates are device-agnostic, though different variants may be needed for different OS output formats. Netmiko ships with a large library of community-contributed TextFSM templates..
Both Python libraries convert unstructured CLI output into structured data, but they take different approaches.
Many production workflows use a hybrid approach: pyATS/Genie for reliable Cisco parsers and TextFSM for gaps or non-Cisco devices.
Use TextFSM when:
Use pyATS/Genie when:
Comparison:
|
TextFSM |
pyATS/Genie |
---|---|---|
Parser Creation |
Manual template writing |
Pre-built (500+ Cisco parsers) |
Accuracy |
Depends on template |
Very high (Cisco-maintained) |
Vendor Coverage |
Any (if you write template) |
Best on Cisco, limited others |
Maintenance |
You maintain templates |
Cisco maintains parsers |
Complexity |
Simple regex patterns |
Complex state machines |
Learning Curve |
Easy |
Moderate |
Output Format |
List of dicts |
Nested dicts (structured) |
Jinja2 is a powerful Python templating engine. It's perfect for creating device configurations from structured data (like YAML or JSON).
How it works:
Why it's great:
Where to use it: Creating configs for L3 interfaces, BGP/OSPF/IS-IS peers, QoS policies, ACLs, and those essential "golden configurations."
Example – Render a Cisco IOS-XE BGP config from YAML data:
# pip install jinja2 pyyaml
from jinja2 import Environment, BaseLoader
import yaml
data = yaml.safe_load("""
hostname: edge1
asn: 65001
router_id: 192.0.2.1
neighbors:
- ip: 203.0.113.2
remote_as: 65002
desc: "upstream-1"
address_family: ["ipv4", "ipv6"]
""")
tpl = """
hostname
router bgp
bgp router-id
neighbor remote-as
neighbor description
address-family ipv4
neighbor activate
exit-address-family
address-family ipv6
neighbor activate
exit-address-family
"""
print(Environment(loader=BaseLoader).from_string(tpl).render(**data))
Multi-vendor Support: Jinja2 itself is vendor-neutral. You can create different templates (e.g., cisco_iosxe.j2, juniper_junos.j2) that take the same YAML data and output vendor-specific configurations.
Pydantic is a Python library for defining data models and validating them using standard Python type hints.
How it works:
Why it's great:
Where to use it: Validating inventory data, site details, BGP policies, VLAN/IPAM info, and API payloads.
Example – Validating a Layer 3 interface intent:
# pip install pydantic
from pydantic import BaseModel, IPvAnyInterface, Field
from typing import Literal
class L3Interface(BaseModel):
name: str
address: IPvAnyInterface
vrf: str = "default"
enabled: bool = True
platform: Literal["iosxe","nxos","iosxr"]
intf = L3Interface(name="Loopback0", address="192.0.2.1/32", platform="iosxe")
print(intf.model_dump()) # safe to feed into Jinja2 or NAPALM
Multi-vendor Support: You can create a single Pydantic model with a platform field and then use custom validators to enforce rules specific to each vendor.
HTTPX is a modern, full-featured Python library for making HTTP requests (sync and async). It handles HTTP/1.1 and HTTP/2, connection pooling, timeouts, and retries. It's perfect for interacting with network controllers and device APIs. (The older Requests library is also great but lacks async support).
How it works:
Why it's great:
Where to use it: Automating Cisco Catalyst Center, Cisco vManage (SD-WAN), Meraki Dashboard, ACI APIC, device-level RESTCONF/NETCONF gateways, and integrating with third-party ITSM/CMDB tools.
Example – List interfaces from Cisco IOS-XE via RESTCONF:
# pip install httpx
import httpx, urllib3
urllib3.disable_warnings() # demo only
host = "10.0.0.11"
auth = ("admin","admin")
headers = {"Accept":"application/yang-data+json"}
url = f"https://{host}/restconf/data/ietf-interfaces:interfaces"
with httpx.Client(verify=False, timeout=20) as c:
r = c.get(url, headers=headers, auth=auth)
r.raise_for_status()
for iface in r.json()["ietf-interfaces:interfaces"]["interface"]:
print(iface["name"], iface.get("enabled", True))
Catalyst Center (DNA Center) – get token + list devices
import httpx, urllib3
urllib3.disable_warnings()
BASE = "https://dnac.example.com"
cred = ("admin","password")
with httpx.Client(base_url=BASE, verify=False, timeout=30) as c:
t = c.post("/dna/system/api/v1/auth/token", auth=cred)
t.raise_for_status()
token = t.json()["Token"]
headers = {"X-Auth-Token": token}
r = c.get("/dna/intent/api/v1/network-device", headers=headers)
r.raise_for_status()
devices = [(d["hostname"], d["managementIpAddress"]) for d in r.json()["response"]]
print(devices)
Meraki Dashboard – simple org list
API_KEY = "xxxxxxxx"
with httpx.Client(base_url="https://api.meraki.com/api/v1", headers={"X-Cisco-Meraki-API-Key": API_KEY}) as c:
r = c.get("/organizations")
r.raise_for_status()
print([o["name"] for o in r.json()])
Multi-vendor Support: Use the same HTTPX client patterns for REST APIs from Arista CloudVision, Juniper Apstra, FortiManager, and other controllers.
PyYAML is the most popular Python library for working with YAML files – that human-readable data format that's the backbone of Ansible and many network automation data models.
How it works:
Why it's great:
Where to use it: Defining device inventories, site-specific variables, policy lists, and feeding data into Jinja2 templates.
Example – Merging inventory data from different YAML files:
groups.yml:
# groups.yaml
iosxe:
data:
platform: iosxe
snmp_community: "netops-ro"
ntp: ["time.google.com","time.cloudflare.com"]
nxos:
data:
platform: nxos
ntp: ["time.cloudflare.com","time.google.com"]
hosts.yml:
# hosts.yaml
edge1:
hostname: 10.0.0.11
groups: [iosxe]
spine1:
hostname: 10.0.0.12
groups: [nxos]
data:
snmp_community: "dc-ro"
Python script to merge and use this data:
# Python merge (PyYAML)
import yaml
groups = yaml.safe_load(open("groups.yaml"))
hosts = yaml.safe_load(open("hosts.yaml"))
print(hosts["spine1"]["data"]["snmp_community"]) # dc-ro (override)
Multi-vendor Support: Organize your YAML files logically (by platform, device role, etc.). The format itself is vendor-neutral.
Here are common scenarios network engineers face and which Python libraries solve them:
Scenario 1: Automated Configuration Backup
Scenario 2: Compliance Auditing
Scenario 3: Network Health Dashboard
Scenario 4: A Modern Change Management Pipeline
Python libraries are essential tools for modern network engineers. They help you move beyond manual CLI tasks, enabling you to build automation that is consistent, scalable, and reliable. Whether you're just starting out with Netmiko or building complex orchestration with Nornir, these libraries will significantly boost your efficiency and reduce errors.
The best way to learn? Practice. Use tools like GNS3, EVE-NG, or Cisco Modeling Labs (especially hosted solutions like CloudMyLab) to build realistic network scenarios.
Practice until automation becomes second nature. When you're ready to test, we're ready to provide the lab environment.
Explore CloudMyLab's Network Automation Labs →
It depends on the task: Netmiko for CLI tasks, NAPALM for config management and multi-vendor consistency, Nornir for orchestrating tasks across many devices, Scrapli for high-performance and async operations, pyATS/Genie for deep Cisco testing and parsing, Jinja2 for rendering configs, and HTTPX for APIs.
Nope. Start with the basics like Netmiko, PyYAML, and Jinja2. Then, add others as your needs grow. Many engineers become very effective using just a handful of these.
Start with Netmiko. It’s simpler and teaches the core concepts of SSH automation. Then move to NAPALM for its multi-vendor config management features.
With existing network knowledge: Basic scripting (Netmiko) might take 2-4 weeks of consistent practice. Intermediate workflows (Nornir, Jinja2) could take 2-3 months to become proficient. Building production-ready pipelines will take longer, perhaps 4-6 months or more.
The key is practice. Automate one real task each week rather than trying to learn everything at once. Understanding network engineer certifications and career paths can help you plan your automation learning journey alongside traditional networking skills.
Yes! Many teams use Ansible for broader IT automation and these Python libraries for specific network tasks or when they need more control/performance. You can call Python scripts from Ansible playbooks or use Ansible's Python API.
FFor CLI automation, Netmiko supports over 100 device types. If yours isn't listed, try the "generic" device type, create a custom Scrapli driver, use Paramiko directly, or look for community support to add your device type.
Yes, there are alternatives like Fabric (another async SSH library), the Ansible Python API, netdev, and various vendor-specific SDKs. However, these ten libraries are the most widely adopted and powerful for general network automation.
You should learn both. Use Python for custom logic, heavy data processing, high performance needs, or network-specific workflows if your team is comfortable with Python. Use Ansible when your team prefers declarative YAML, needs to automate across a broader IT scope, wants to leverage ready-made modules, or requires enterprise features like a GUI and RBAC. Many successful teams use both.
Practice environments are essential for learning Python automation without risking production networks. Options include:
Cloud-based labs: Cloud-based training labs provide on-demand access to realistic network topologies without hardware investment
Network emulators: Boost your network simulation skills using GNS3, EVE-NG, or CML 2.0 with virtual routers and switches
Cisco DevNet sandboxes: Free always-on and reservable lab environments
Vendor lab environments: Trial accounts from network equipment manufacturers
For comprehensive practice, network simulators for CCNA, CCNP, and CCIE exam prep offer structured learning paths that include automation components.
Always test automation scripts in a lab environment before running against production devices. This protects your network while you learn and validates your code logic.