Python循环填充字典仅返回最后一个IP数据的问题排查
从netstat提取了一批端点IP并存储在列表中,尝试通过enrich_ip函数为每个IP添加GeoIP信息,但循环结束后字典仅保留最后一个IP的信息。此前在函数外实现时功能正常,封装成函数后出现数据覆盖问题。
调试信息
DEBUG1: Endpoint IPs: ['165.227.118.82', '155.133.248.39', '20.54.37.64', '173.194.76.188', '74.125.206.109', '47.251.49.246', '52.19.109.21', '151.101.61.229', '151.101.60.193', '162.159.133.234', '162.159.135.232', '162.159.133.232', '162.159.129.232', '75.2.53.94', '54.170.196.176', '143.204.65.104', '34.236.20.64', '75.101.134.98', '75.101.134.98', '75.101.134.98', '52.216.249.68', '52.216.249.68', '142.250.179.228', '142.250.179.228', '52.96.165.18', '52.97.133.194', '52.98.159.194']
DEBUG2: Enriched IP: {'IP': '52.98.159.194', 'continent': 'Europe', 'country': 'France', 'iso_code': 'FR', 'city': 'Paris', 'lat': 48.8323, 'long': 2.4075, 'timezone': 'Europe/Paris', 'accuracy': 20}
问题代码
def enrich_ip(rip): enriched_info = {} for ip in rip: try: enriched_info['IP'] = ip enriched_info['continent'] = get_ip_info(ip).continent.name enriched_info['country'] = get_ip_info(ip).country.name enriched_info['iso_code'] = get_ip_info(ip).country.iso_code enriched_info['city'] = get_ip_info(ip).city.name enriched_info['lat'] = get_ip_info(ip).location.latitude enriched_info['long'] = get_ip_info(ip).location.longitude enriched_info['timezone'] = get_ip_info(ip).location.time_zone enriched_info['accuracy'] = get_ip_info(ip).location.accuracy_radius except Exception as e: print(e) continue return enriched_info
问题原因
enriched_info被定义为单个字典,循环过程中每次迭代都会覆盖字典内的所有键值对,最终仅保留最后一次循环的IP数据。函数外实现正常,是因为当时大概率每次循环都会将生成的字典存入列表,而封装成函数后错误地复用了同一个字典对象。
修复方案
将enriched_info改为列表存储,每次循环创建新字典并添加到列表中,同时优化get_ip_info的调用次数以提升效率:
def enrich_ip(rip): enriched_info = [] # 改为列表存储多个IP的信息 for ip in rip: try: ip_info = {} # 每次循环创建新字典 geo_data = get_ip_info(ip) # 仅调用一次GeoIP接口,减少开销 ip_info['IP'] = ip ip_info['continent'] = geo_data.continent.name ip_info['country'] = geo_data.country.name ip_info['iso_code'] = geo_data.country.iso_code ip_info['city'] = geo_data.city.name ip_info['lat'] = geo_data.location.latitude ip_info['long'] = geo_data.location.longitude ip_info['timezone'] = geo_data.location.time_zone ip_info['accuracy'] = geo_data.location.accuracy_radius enriched_info.append(ip_info) # 将新字典加入列表 except Exception as e: print(e) continue return enriched_info
内容的提问来源于stack exchange,提问作者twelsh37

