Python+Netmiko处理Cisco交换机无效IP地址异常求助
问题背景
我用Python结合Netmiko库开发工具,登录Cisco交换机并清除Port Security粘性条目,需求是:
- 提示用户输入交换机IP地址
- 输入无效/无法连接的IP时,给不熟悉交换机操作的用户友好提示
- 异常提示后允许重新输入IP
当前问题:输入无效IP会触发socket.gaierror和netmiko.exceptions.NetmikoTimeoutException,但现有代码的异常捕获逻辑无效——因为ConnectHandler不在try代码块内,连接阶段的异常无法被捕获。
报错信息
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\netmiko\base_connection.py", line 1046, in establish_connection
self.remote_conn_pre.connect(**ssh_connect_params)
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\paramiko\client.py", line 340, in connect
to_try = list(self._families_and_addresses(hostname, port))
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\paramiko\client.py", line 203, in _families_and_addresses
addrinfos = socket.getaddrinfo(
File "C:\Users\jesse.garcia\Anaconda3\lib\socket.py", line 954, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [错误号11001] getaddrinfo失败在处理上述异常期间,又触发了新的异常:
Traceback (most recent call last):
File "C:\Users\jesse.garcia\Documents\GitHub\python\Practice OOP\practicce.py", line 18, in
net_connect = ConnectHandler(**cisco_881)
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\netmiko\ssh_dispatcher.py", line 365, in ConnectHandler
return ConnectionClass(*args, **kwargs)
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\netmiko\base_connection.py", line 439, in init
self._open()
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\netmiko\base_connection.py", line 444, in _open
self.establish_connection()
File "C:\Users\jesse.garcia\Anaconda3\lib\site-packages\netmiko\base_connection.py", line 1068, in establish_connection
raise NetmikoTimeoutException(msg)
netmiko.exceptions.NetmikoTimeoutException: TCP连接设备失败。常见原因:
- 主机名或IP地址错误
- TCP端口错误
- 中间防火墙拦截访问
设备配置:cisco_ios +95:22*
现有代码问题分析
核心问题是ConnectHandler(**cisco_881)这行创建连接的代码不在try块内,连接失败时抛出的异常直接终止程序,根本不会进入后续针对send_command的异常捕获逻辑,所有之前尝试的捕获方式都因此无效。
修正后的代码
from netmiko import ConnectHandler import netmiko import socket if __name__ == "__main__": while True: # 获取用户输入 ipadd = input("请输入交换机的IP地址:") port = input("请输入端口号(如1、2等):") # 设备配置 cisco_device = { 'device_type': 'cisco_ios', 'host': ipadd, 'username': '', # 替换为实际用户名 'password': '', # 替换为实际密码 'port': 22, 'secret': '', } try: # 建立连接(关键:将ConnectHandler放入try块内) net_connect = ConnectHandler(**cisco_device) # 执行Port Security清除命令 output = net_connect.send_command(f'clear port-security sticky int g1/0/{port}') print(f"命令执行成功!输出信息:\n{output}") net_connect.disconnect() # 执行完成后断开连接 break # 操作成功,退出循环 except (socket.gaierror, netmiko.exceptions.NetmikoTimeoutException): print("⚠️ 输入的IP地址无效或无法连接到交换机,请重新输入!") except netmiko.exceptions.NetmikoAuthenticationException: print("⚠️ 用户名或密码错误,请检查后重新输入!") except Exception as e: print(f"⚠️ 发生未知错误:{str(e)}")
关键改进说明
- 覆盖连接阶段异常:把
ConnectHandler放入try块内,确保连接失败时的异常能被捕获 - 循环输入逻辑:用
while True实现失败后重新输入IP的功能,直到操作成功 - 友好提示:针对不同异常给出对应提示,符合普通用户认知
- 资源清理:命令执行成功后主动断开连接,避免占用SSH资源
- 扩展异常捕获:增加认证失败的异常处理,覆盖更多常见错误场景
内容的提问来源于stack exchange,提问作者Jesse Garcia

