4. Python网络自动化基础

在真正让脚本登录一台 Catalyst 交换机之前,需要先补齐 Python 的几项基础能力:用合适的数据类型承载设备信息与命令输出,用文件操作保存配置和日志,用异常处理应对 SSH 超时、认证失败等现实问题,再借助 requests 与 ncclient 两类库分别完成 RESTCONF/NETCONF 交互。本节围绕“第一次自动化交互”这一目标,把这些基础能力串成一条可执行的路径。

一、用数据类型描述网络对象

网络自动化中,最常用的数据类型是字符串、整数、布尔值、列表和字典。字符串用于设备名、IP、接口名;整数用于 VLAN ID、端口号;布尔值用于表示接口是否启用;列表适合存放多台设备或多条命令;字典则适合描述一台设备的多个属性。例如一台 Catalyst 设备的登录信息可以写成:

device = {
    "host": "10.10.10.21",
    "username": "netadmin",
    "password": "C1sco!2024",
    "port": 22,
    "device_type": "cisco_ios"
}

当需要批量操作时,把多台设备的字典放进列表,就形成了设备清单:

devices = [
    {"host": "10.10.10.21", "name": "C9300-Core-1"},
    {"host": "10.10.10.22", "name": "C9300-Core-2"},
    {"host": "10.10.10.23", "name": "C9200-Access-1"}
]

这里要特别注意:字典取值用 device["host"],列表遍历用 for d in devices。如果键名写错,Python 会抛出 KeyError,这正是后面异常处理要覆盖的场景。

二、文件操作:让配置与日志落地

自动化脚本不能只把结果打印在屏幕上,通常需要把设备回显、配置备份或执行日志写入文件。推荐使用 with open(...) 上下文管理器,确保文件在异常时也能正确关闭:

with open("backup/C9300-Core-1.cfg", "w", encoding="utf-8") as f:
    f.write(running_config)

读取设备清单时,常用 JSON 文件保存结构化数据:

import json

with open("devices.json", "r", encoding="utf-8") as f:
    devices = json.load(f)

文件路径建议使用相对路径配合目录创建,例如 os.makedirs("backup", exist_ok=True),避免因目录不存在导致 FileNotFoundError。写入模式 "w" 会覆盖原文件,追加日志应使用 "a"。

三、异常处理:让脚本在故障中可控

网络自动化的最大现实问题是“设备不一定按预期响应”。因此需要用 try/except/finally 包裹关键操作。典型结构如下:

from netmiko import ConnectHandler

try:
    conn = ConnectHandler(**device)
    output = conn.send_command("show version")
except TimeoutError:
    print(f"{device['host']} 连接超时")
except Exception as e:
    print(f"{device['host']} 连接失败: {e}")
finally:
    if 'conn' in locals():
        conn.disconnect()

这里 TimeoutError 对应 SSH 无响应,Exception 兜底捕获认证失败、协议不匹配等错误。finally 保证无论成功与否都断开连接,避免会话残留。实际排障时,建议把异常信息写入日志文件,而不是只打印到终端。

四、requests 与 ncclient:两条交互路径

Catalyst 设备支持多种管理接口。若设备启用了 RESTCONF,可用 requests 发送 HTTP 请求:

import requests

url = "https://10.10.10.21/restconf/data/ietf-interfaces:interfaces"
headers = {"Accept": "application/yang-data+json"}
resp = requests.get(url, headers=headers,
                    auth=("netadmin", "C1sco!2024"), verify=False)
print(resp.status_code, resp.json())

若设备启用 NETCONF,则用 ncclient 建立会话并获取配置:

from ncclient import manager

with manager.connect(host="10.10.10.21", port=830,
                     username="netadmin", password="C1sco!2024",
                     hostkey_verify=False) as m:
    cfg = m.get_config(source="running")
    print(cfg.xml)

requests 适合 RESTCONF 的 JSON 数据流,ncclient 适合 NETCONF 的 XML 数据流。两者都需要先确认设备已开启对应服务,并注意 verify=False 仅用于实验环境。

Python 首次自动化交互 Catalyst 设备的数据流 Python 脚本 数据类型 dict / list / str / int 文件操作 open / json.load / write 异常处理 try / except / finally requests RESTCONF / JSON ncclient NETCONF / XML 管理通道 SSH / 22 CLI 命令 HTTPS / 443 RESTCONF NETCONF / 830 XML RPC Catalyst 交换机 管理平面 SSH / RESTCONF / NETCONF AAA 认证 控制平面 running-config 接口 / VLAN / 路由表 数据平面 转发 / 状态 / 计数器 show 命令输出 异常场景 超时 / 认证失败 / 协议未启用 实线:请求方向 虚线:响应/回显方向 异常在脚本侧由 try/except 捕获

五、首次自动化交互的完整示例

把上述能力组合起来,一个最小可用的首次交互脚本如下。它读取设备清单、逐台连接、执行 show version、保存回显,并对异常做记录:

import json, os
from netmiko import ConnectHandler

os.makedirs("output", exist_ok=True)

with open("devices.json", "r", encoding="utf-8") as f:
    devices = json.load(f)

for dev in devices:
    try:
        conn = ConnectHandler(
            device_type="cisco_ios",
            host=dev["host"],
            username="netadmin",
            password="C1sco!2024",
            timeout=10
        )
        ver = conn.send_command("show version")
        with open(f"output/{dev['name']}_version.txt", "w", encoding="utf-8") as out:
            out.write(ver)
        print(f"{dev['name']} 采集成功")
        conn.disconnect()
    except Exception as e:
        print(f"{dev['name']} 失败: {e}")

判断脚本是否成功,可以看三个信号:终端是否逐台打印“采集成功”;output/ 目录下是否生成对应文件;文件内容是否包含 Cisco IOS Software 与版本号。若某台设备失败,异常信息会指出是超时、认证还是协议问题,便于针对性排查。

实验环境建议先用一台设备验证连通性,再扩展到多台;密码不要硬编码在脚本中,可改用环境变量或 getpass 输入。
requests 的 verify=False 与 ncclient 的 hostkey_verify=False 会跳过证书/主机密钥校验,仅限实验环境使用,生产环境应导入正确证书。