Python for循环中字典无法追加列表数据仅存储最后IP数据问题
问题原因
字典数据被覆盖是变量作用域和存储逻辑错误导致的:
- 你把
ospfdict、ospfdictkey的初始化逻辑写在了for循环内部,每遍历一个IP就会重新创建空字典,上一轮循环存入的前序设备数据会被直接清空 - 两种写入方法都存在循环内覆盖问题:
- METHOD1:每次循环新建空字典后,仅追加当前设备的数据,循环结束自然只保留最后一台设备的内容,还因为直接append列表导致数据多嵌套一层
- METHOD2:每次循环直接给字典键重新赋值,新值完全覆盖旧值,不会保留历史数据
- 最后传给模板的所有变量都是循环最后一次赋值的单设备结果,没有做跨设备的数据聚合,无法拿到3台设备的全量信息
- 循环结束后直接执行
listip.clear(),前端拿到的IP列表永远是空值
修复方案
把多设备数据的聚合存储容器移到for循环外部初始化,每处理完一台设备就把当前数据追加到聚合容器中,禁止在循环内重建存储全量数据的字典/列表。
修复后的完整代码如下:
def healthcheckresults(request): if not listip: return render(request, "home/homepage.html") # 全量数据聚合容器必须放在循环外部初始化,避免每次遍历被重置 all_device_data = [] # 按设备维度存储结构化数据,前端遍历即可逐台渲染 all_ospfneighboraddress = [] all_ospfneighborinterface = [] all_ospfneighborstate = [] all_ospfneighborID = [] all_hostname = [] all_context = [] # 直接遍历IP列表即可,无需通过range取索引访问 for ip in listip: conn = manager.connect( host=ip, port='22', username='XXX', password='XXX', timeout=10 ) result = conn.get_ospf_neighbor_information() hostnameresult = conn.get_software_information() # 提取当前设备数据,xpath默认返回列表,取第一个值转为字符串,增加判空避免报错 hostname_res = hostnameresult.xpath('//software-information/host-name/text()') hostname = hostname_res[0] if hostname_res else "未知设备" ospfneighboraddress = result.xpath('//ospf-neighbor/neighbor-address/text()') ospfneighborinterface = result.xpath('//ospf-neighbor/interface-name/text()') ospfneighborstate = result.xpath('//ospf-neighbor/ospf-neighbor-state/text()') ospfneighborID = result.xpath('//ospf-neighbor/neighbor-id/text()') # 组装当前单台设备的独立字典 current_device = { "hostname": hostname, "ospfneighboraddress": ospfneighboraddress, "ospfneighborinterface": ospfneighborinterface, "ospfneighborstate": ospfneighborstate, "ospfneighborID": ospfneighborID } # 将当前设备数据追加到全量列表 all_device_data.append(current_device) # 按字段聚合所有设备数据,兼容原有模板传参逻辑 all_hostname.append(hostname) all_ospfneighboraddress.extend(ospfneighboraddress) all_ospfneighborinterface.extend(ospfneighborinterface) all_ospfneighborstate.extend(ospfneighborstate) all_ospfneighborID.extend(ospfneighborID) all_context.append({ "device_hostname": hostname, "LUnique": zip(ospfneighboraddress, ospfneighborinterface, ospfneighborstate, ospfneighborID) }) conn.close_session() # 如需清空IP列表,建议在模板传参完成后执行,避免前端拿到空值 # listip.clear() return render(request, "healthcheck/healthcheckresults.html", { "all_device_data": all_device_data, "ospfneighboraddress": all_ospfneighboraddress, "ospfneighborinterface": all_ospfneighborinterface, "ospfneighborstate": all_ospfneighborstate, "ospfneighborID": all_ospfneighborID, "context_list": all_context, "hostname": all_hostname, "listip": listip })
前端渲染参考
逐台展示设备OSPF信息时,直接在模板中遍历all_device_data即可,示例代码:
{% for device in all_device_data %} <div class="device-block"> <h3>设备:{{ device.hostname }}</h3> <table border="1" cellpadding="6" cellspacing="0"> <thead> <tr> <th>OSPF邻居地址</th> <th>连接接口</th> <th>邻居状态</th> <th>邻居Router ID</th> </tr> </thead> <tbody> {% for addr, intf, state, nid in device.ospfneighboraddress|zip:device.ospfneighborinterface|zip:device.ospfneighborstate|zip:device.ospfneighborID %} <tr> <td>{{ addr }}</td> <td>{{ intf }}</td> <td>{{ state }}</td> <td>{{ nid }}</td> </tr> {% endfor %} </tbody> </table> </div> {% endfor %}
内容的提问来源于stack exchange,提问作者justhelpme
相关产品推荐
相关产品推荐

