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行以内的个人项目,面试时能讲清每个模块的职责和异常处理边界,比背诵语法点更有竞争力。