Python多列表循环校验逻辑错误,输出结果不符合预期
问题排查:Python校验逻辑错误导致异常输出
现有代码
statuses = [ {'id': '1', 'plan_id': '124124124', 'ip': '1.1.1.1', 'name': 'Saeed1', 'status': 'active'}, {'id': '2', 'plan_id': '124224124', 'ip': '2.2.2.2', 'name': 'Saeed2', 'status': 'suspended'}, {'id': '3', 'plan_id': '164124124', 'ip': '3.3.3.3', 'name': 'Saeed3', 'status': 'suspended'}, {'id': '4', 'plan_id': '164124124', 'ip': '4.4.4.4', 'name': 'Saeed4', 'status': 'suspended'}, {'id': '5', 'plan_id': '124124124', 'ip': '5.5.5.5', 'name': 'Saeed51', 'status': 'active'}, ] all_servers = [ {'id': '1', 'name': 'Saeed1', 'addresses': {'External_Network': [{'addr': '1.1.1.1'}]}, 'plan': 'planA', 'status': 'suspended'}, {'id': '2', 'name': 'Saeed2', 'addresses': {'External_Network': [{'addr': '6.6.6.6'}]}, 'plan': 'planB', 'status': 'suspended'}, {'id': '3', 'name': 'Saeed3', 'addresses': {'External_Network': [{'addr': '3.3.3.3'}]}, 'plan': 'planG', 'status': 'active'}, {'id': '4', 'name': 'Saeed4', 'addresses': {}, 'plan': 'planC', 'status': 'active'}, {'id': '5', 'name': 'Saeed5', 'addresses': {'External_Network': [{'addr': '8.8.8.8'}]}, 'plan': 'planA', 'status': 'suspended'}, ] all_plans = [ {'name': 'planA', 'id': '124124124'}, {'name': 'planB', 'id': '124224124'}, {'name': 'planC', 'id': '164124124'}, {'name': 'planG', 'id': '174124124'}, ] tmp = [] final = [] for status in statuses: for server in all_servers: for plan in all_plans: if status['id'] == server['id'] and status['id'] not in tmp: tmp.append(status['id']) if (status['plan_id'] != plan['id']) and (plan['name'] != server['plan']): final.append({'name': status['name'], 'code': 'plan_mismatch'}) if 'External_Network' not in server['addresses']: final.append({'name': server['name'], 'code': 'has no ip'}) else: for addr in server['addresses']['External_Network']: if addr['addr'] != status['ip']: final.append({'name': status['name'], 'code': 'ip_mismatch'}) if status['status'] != server['status']: final.append({'name': status['name'], 'code': 'status_mismatch'}) if status['name'] != server['name']: final.append({'name': status['name'], 'code': 'names_mismatch'})
校验逻辑
从
statuses和all_servers中,先匹配id,再执行以下校验:
- 若
status['plan_id'] != plan['id']且plan['name'] != server['plan'],记录plan_mismatch- 若
status['name'] != server['name'],记录names_mismatch- 若
status['ip'] != server['addresses']['External_Network']['addr'],记录ip_mismatch- 若
status['status'] != server['status'],记录status_mismatch
当前问题
当前final列表出现不应存在的异常项:
- {'name': 'Saeed2', 'code': 'plan_mismatch'}
- {'name': 'Saeed4', 'code': 'plan_mismatch'}
预期输出
预期的正确异常输出应为:
- Saeed1 status_mismatch
- Saeed2 ip_mismatch
- Saeed3 plan_mismatch
- Saeed3 status_mismatch
- Saeed4 has no ip
- Saeed4 status_mismatch
- Saeed51 name_mismatch
- Saeed51 ip_mismatch
- Saeed51 status_mismatch
错误分析
- 嵌套循环逻辑错误:原代码将
plan循环放在最内层,导致每匹配到一个id,就会遍历所有plan,只要有任意一个plan不满足status['plan_id'] == plan['id']且plan['name'] == server['plan'],就会触发plan_mismatch,完全偏离了“找到对应server的plan再对比”的需求。 - plan校验条件错误:原条件
(status['plan_id'] != plan['id']) and (plan['name'] != server['plan'])逻辑完全错误,正确逻辑应该是:找到server对应的plan(即plan['name'] == server['plan']),然后检查该plan的id是否不等于status的plan_id。 - 冗余的去重逻辑:
tmp列表用于避免重复处理id,但通过匹配server后直接break循环,即可保证每个id只处理一次,无需额外去重。
修正后的代码
statuses = [ {'id': '1', 'plan_id': '124124124', 'ip': '1.1.1.1', 'name': 'Saeed1', 'status': 'active'}, {'id': '2', 'plan_id': '124224124', 'ip': '2.2.2.2', 'name': 'Saeed2', 'status': 'suspended'}, {'id': '3', 'plan_id': '164124124', 'ip': '3.3.3.3', 'name': 'Saeed3', 'status': 'suspended'}, {'id': '4', 'plan_id': '164124124', 'ip': '4.4.4.4', 'name': 'Saeed4', 'status': 'suspended'}, {'id': '5', 'plan_id': '124124124', 'ip': '5.5.5.5', 'name': 'Saeed51', 'status': 'active'}, ] all_servers = [ {'id': '1', 'name': 'Saeed1', 'addresses': {'External_Network': [{'addr': '1.1.1.1'}]}, 'plan': 'planA', 'status': 'suspended'}, {'id': '2', 'name': 'Saeed2', 'addresses': {'External_Network': [{'addr': '6.6.6.6'}]}, 'plan': 'planB', 'status': 'suspended'}, {'id': '3', 'name': 'Saeed3', 'addresses': {'External_Network': [{'addr': '3.3.3.3'}]}, 'plan': 'planG', 'status': 'active'}, {'id': '4', 'name': 'Saeed4', 'addresses': {}, 'plan': 'planC', 'status': 'active'}, {'id': '5', 'name': 'Saeed5', 'addresses': {'External_Network': [{'addr': '8.8.8.8'}]}, 'plan': 'planA', 'status': 'suspended'}, ] all_plans = [ {'name': 'planA', 'id': '124124124'}, {'name': 'planB', 'id': '124224124'}, {'name': 'planC', 'id': '164124124'}, {'name': 'planG', 'id': '174124124'}, ] # 将plan列表转为字典,通过名称快速获取ID,提升效率 plan_name_to_id = {plan['name']: plan['id'] for plan in all_plans} final = [] for status in statuses: # 匹配对应ID的server for server in all_servers: if status['id'] == server['id']: # 校验名称 if status['name'] != server['name']: final.append({'name': status['name'], 'code': 'names_mismatch'}) # 校验状态 if status['status'] != server['status']: final.append({'name': status['name'], 'code': 'status_mismatch'}) # 校验IP if 'External_Network' not in server['addresses'] or not server['addresses']['External_Network']: final.append({'name': server['name'], 'code': 'has no ip'}) else: server_ip = server['addresses']['External_Network'][0]['addr'] if server_ip != status['ip']: final.append({'name': status['name'], 'code': 'ip_mismatch'}) # 校验plan server_plan_id = plan_name_to_id.get(server['plan']) if server_plan_id != status['plan_id']: final.append({'name': status['name'], 'code': 'plan_mismatch'}) # 找到匹配server后跳出循环,避免重复处理 break # 输出结果 for item in final: print(f"{item['name']} {item['code']}")
修正说明
- 优化plan查找:将
all_plans转为字典plan_name_to_id,直接通过server的plan名称获取对应ID,避免无效循环。 - 调整循环结构:先匹配status和server的ID,找到对应server后一次性完成所有校验,不再遍历所有plan。
- 修正plan校验逻辑:正确获取server对应的plan ID,再与status的plan_id对比,不相等则记录异常。
- 完善IP校验:增加对
External_Network为空列表的判断,直接取第一个IP地址(符合原数据结构)。 - 移除冗余代码:删除
tmp列表,通过break循环保证每个ID只处理一次。
内容的提问来源于stack exchange,提问作者Saeed
相关产品推荐
相关产品推荐

