3. Python网络自动化面试核心

网络自动化岗位的Python面试,很少考算法竞赛题,更关注你能否用Python稳定地处理设备配置、解析回显、管理依赖。本章围绕六个高频考点展开,每个考点都给出面试常见问法与可落地的实现方式。

一、数据类型:面试官想看你是否理解“可变与不可变”

网络自动化中,设备清单、接口状态、路由表通常用列表和字典承载。面试常问:“为什么用字典存设备信息而不是列表?”关键在于字典以设备名为键,查找复杂度为O(1),而列表需要遍历。例如:

devices = {
    "core-sw-01": {"ip": "10.0.0.1", "vendor": "cisco", "protocol": "ssh"},
    "edge-rtr-01": {"ip": "10.0.0.2", "vendor": "huawei", "protocol": "netconf"}
}
print(devices["core-sw-01"]["ip"])  # 10.0.0.1

另一个高频点是可变对象作为默认参数。下面这个函数是面试陷阱:

def add_device(device, pool=[]):
    pool.append(device)
    return pool

print(add_device("sw1"))  # ['sw1']
print(add_device("sw2"))  # ['sw1', 'sw2'],而非预期 ['sw2']

原因是默认参数在函数定义时只求值一次,列表被复用。正确写法是 pool=None,函数体内再判断并初始化。面试中能主动指出这一点,说明你写过真实脚本。

二、文件处理:配置备份与批量读取

网络自动化脚本经常要读取设备列表文件、写入配置备份。面试常考上下文管理器和编码问题。推荐写法:

with open("devices.txt", encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line or line.startswith("#"):
            continue
        host, ip = line.split(",")
        print(host, ip)

使用 with 可确保文件关闭;逐行迭代避免大文件占内存;跳过空行和注释行是工程习惯。写入备份时建议用 newline="" 避免Windows下多出空行:

with open("backup.cfg", "w", encoding="utf-8", newline="") as f:
    f.write(config_text)

三、异常处理:网络脚本必须区分“可重试”与“不可重试”

面试官常问:“设备连不上时你怎么处理?”标准答案是捕获具体异常并分类处理,而不是裸 except。示例:

import socket
from netmiko import ConnectHandler, NetmikoTimeoutException, NetmikoAuthenticationException

def connect(device):
    try:
        conn = ConnectHandler(**device)
        return conn
    except NetmikoAuthenticationException:
        print(f"{device['host']} 认证失败,检查用户名密码")
        return None
    except NetmikoTimeoutException:
        print(f"{device['host']} 连接超时,检查可达性")
        return None
    except socket.error as e:
        print(f"{device['host']} 网络错误: {e}")
        return None

认证失败重试无意义,超时可重试一次,网络错误需先排查链路。面试中能说出“异常分类决定重试策略”,比背语法更有说服力。同时注意 finally 用于释放连接,else 用于无异常时的后续操作。

四、正则解析:从show命令回显中提取结构化数据

面试常给一段回显让你写正则。例如解析接口状态:

import re

output = """GigabitEthernet0/1  is up, line protocol is up
  Internet address is 10.1.1.1/24
GigabitEthernet0/2  is down, line protocol is down
  Internet address is 10.1.1.2/24"""

pattern = re.compile(
    r"(?P<intf>\S+)\s+is\s+(?P<status>up|down).*?"
    r"Internet address is\s+(?P<ip>[\d.]+/\d+)",
    re.S
)
for m in pattern.finditer(output):
    print(m.group("intf"), m.group("status"), m.group("ip"))

要点:使用命名分组提高可读性;re.S 让 . 匹配换行;finditer 适合多接口。面试中若被问“正则和TextFSM怎么选”,可答:简单固定格式用正则,多厂商多模板用TextFSM或Genie解析。

五、JSON与YAML:配置数据的序列化与反序列化

JSON适合API交互,YAML适合人工编写配置。面试常考两者转换与安全加载。示例:

import json, yaml

data = {"hostname": "core-sw-01", "vlans": [10, 20, 30]}

# 写JSON
with open("dev.json", "w") as f:
    json.dump(data, f, indent=2)

# 读YAML(安全方式)
with open("dev.yaml") as f:
    cfg = yaml.safe_load(f)

必须强调 yaml.safe_load 而非 yaml.load,后者可能执行任意对象构造,存在安全风险。JSON的 indent 参数便于人工阅读,ensure_ascii=False 可保留中文。面试中若问“YAML锚点怎么用”,可举例:

defaults: &defaults
  protocol: ssh
  port: 22

sw1:
  <<: *defaults
  ip: 10.0.0.1

六、模块化脚本设计与虚拟环境

面试官常问:“你的自动化脚本怎么组织?”推荐分层:inventory.py负责设备清单,connector.py封装连接,tasks.py定义业务动作,main.py做入口。避免把所有逻辑写在一个文件里。

虚拟环境是必问项。标准流程:

python -m venv venv
source venv/bin/activate      # Linux/macOS
venv\Scripts\activate         # Windows
pip install netmiko pyyaml
pip freeze > requirements.txt

面试中要能解释:虚拟环境隔离项目依赖,避免版本冲突;requirements.txt锁定版本保证可复现。若被问“pip和conda区别”,可答:pip管Python包,conda还能管非Python依赖和Python版本本身。

面试速查表

考点 高频问法 关键回答
数据类型 默认参数为何不能用可变对象 定义时求值一次,会跨调用复用
文件处理 大文件怎么读 with + 逐行迭代,避免readlines
异常处理 设备连不上怎么办 捕获具体异常,区分重试策略
正则解析 如何提取接口IP 命名分组 + re.S + finditer
JSON/YAML YAML加载注意什么 用safe_load,禁用load
模块化与依赖 脚本怎么组织 分层模块 + venv + requirements.txt

以上六个考点在实际面试中往往交叉出现。例如让你现场写一个“读取YAML设备清单,连接设备,解析回显,异常时记录日志”的脚本,就同时覆盖了数据类型、文件处理、异常、正则、YAML和模块化。建议准备一个200行以内的个人项目,面试时能讲清每个模块的职责和异常处理边界,比背诵语法点更有竞争力。