Python从列表创建DataFrame时'NoneType'无'keys'属性错误的解决
解决
'NoneType' object has no attribute 'keys'报错问题 问题说明
调用自定义write_csv函数将字典列表写入CSV时触发以下错误,核心原因是listofdicts[0]为None,导致调用.keys()方法失败:
触发错误的代码
def write_csv(listofdicts, filename): with open(filename, 'w') as csvFile: wr = csv.DictWriter(csvFile, fieldnames=listofdicts[0].keys()) wr.writeheader() for el in listofdicts: wr.writerow(el) users_list = create_dicts(total_users_nowar, total_users_z, get_subs = False) write_csv(users_list, 'total_users_r_e1.csv') users_list = create_dicts(total_users_nowar, total_users_z, get_subs = True) write_csv(users_list, 'total_users_with_subs_everyone.csv')
报错回溯
AttributeError Traceback (most recent call last) <ipython-input-48-70aef893aa9b> in <module> 1 #users_list = create_dicts(total_users_nowar, total_users_z, get_subs = False) 2 users_list = create_dicts(total_users_nowar, total_users_z, get_subs = False) ----> 3 write_csv(users_list, 'total_users_r_e1.csv') 4 users_list = create_dicts(total_users_nowar, total_users_z, get_subs = True) 5 write_csv(users_list, 'total_users_with_subs_everyone.csv') <ipython-input-45-3ff341d6bc21> in write_csv(listofdicts, filename) 1 def write_csv(listofdicts, filename): 2 with open(filename, 'w') as csvFile: ----> 3 wr = csv.DictWriter(csvFile, fieldnames=listofdicts[0].keys()) 4 wr.writeheader() 5 for el in listofdicts: AttributeError: 'NoneType' object has no attribute 'keys'
背景与相关函数
该场景是通过VK API分析用户对乌克兰特别军事行动的态度,users_z为支持行动的用户列表,users_nowar为反对行动的用户列表,生成字典列表的核心函数如下:
def create_dict_for_user(user_id, cl, info, get_subs): subs_list = None if get_subs: if not info['is_closed']: subscriptions_list = vk.users.getSubscriptions(user_id=user_id,extended=0) subs_list = subscriptions_list['users']['items']+list(-np.array(subscriptions_list['groups']['items'])) user = {'user_id': user_id, 'cl': cl, 'gender': None, 'age': None, 'country': None, 'city': None, 'political': None, 'life_views': None, 'people_views': None, 'religion': None, 'subscribtions': subs_list, 'education': 'no_info'} if info != []: if 'bdate' in info.keys(): if len(info['bdate'])>5: user['age'] = calculateAge(datetime.strptime(info['bdate'], '%d.%m.%Y')) if 'country' in info.keys(): user['country'] = info['country']['title'] if 'sex' in info.keys(): user['gender'] = gender[info['sex']] if 'city' in info.keys(): user['city'] = info['city']['title'] if 'schools' in info.keys(): user['education'] = 'only_school' if info['schools']!=[]: if 'university' in info.keys(): if info['university']!=[]: user['education'] = 'school_and_uni' else: if 'university' in info.keys(): if info['university']!=[]: user['education'] = 'only_uni' else: if 'university' in info.keys(): user['education'] = 'only_uni' if 'personal' in info.keys(): if info['personal']!=[]: if 'political' in info['personal'].keys(): if info['personal']['political']>0: user['political'] = political_views[info['personal']['political']] if 'life_main' in info['personal'].keys(): if info['personal']['life_main']>0: user['life_views'] = life_views[info['personal']['life_main']] if 'people_main' in info['personal'].keys(): if info['personal']['people_main']>0: user['people_views'] = people_views[info['personal']['people_main']] if 'religion' in info['personal'].keys(): religion = info['personal']['religion'] if religion in religion_list.keys(): user['religion'] = religion_list[religion] else: user['religion'] = 'Другое' print(religion) return user def create_dicts(users_nowar, users_z, get_subs = True): user_list = [] startind = 0 users_nowar_info = [] while startind < len(users_nowar): stopind = min(startind+1000, len(users_nowar)) users_nowar_info += vk.users.get(user_ids = users_nowar[startind:stopind], fields = ['bdate','city','country', 'personal','sex','education','schools']) startind = stopind startind = 0 users_z_info = [] while startind < len(users_z): stopind = min(startind+1000, len(users_z)) users_z_info += vk.users.get(user_ids = users_z[startind:stopind], fields = ['bdate','city','country','personal', 'sex','education','schools']) startind = stopind for i in range(len(users_nowar)): clear_output(wait=True) print('nowar', i) try: user_list.append(create_dict_for_user(users_nowar[i], 'nowar', users_nowar_info[i], get_subs)) except: pass for i in range(len(users_z)): clear_output(wait=True) print('z', i) try: user_list.append(create_dict_for_user(users_z[i], 'z', users_z_info[i], get_subs)) except: pass return user_list
问题原因与解决方法
核心原因
create_dict_for_user函数中,当get_subs=False时,没有定义user字典的代码块,函数默认返回None,导致create_dicts生成的列表中混入None元素。write_csv函数直接取列表第一个元素调用.keys(),未做任何空值或None检查。
修复步骤
1. 修复create_dict_for_user函数
将user字典的定义移到if get_subs:代码块外,确保无论get_subs参数是什么,函数都能返回有效字典:
def create_dict_for_user(user_id, cl, info, get_subs): subs_list = None # 提前定义基础user字典,确保所有分支都能返回有效字典 user = {'user_id': user_id, 'cl': cl, 'gender': None, 'age': None, 'country': None, 'city': None, 'political': None, 'life_views': None, 'people_views': None, 'religion': None, 'subscribtions': subs_list, 'education': 'no_info'} if get_subs: if not info['is_closed']: subscriptions_list = vk.users.getSubscriptions(user_id=user_id,extended=0) subs_list = subscriptions_list['users']['items']+list(-np.array(subscriptions_list['groups']['items'])) user['subscribtions'] = subs_list # 更新订阅信息 # 处理用户信息的逻辑保持不变 if info != []: if 'bdate' in info.keys(): if len(info['bdate'])>5: user['age'] = calculateAge(datetime.strptime(info['bdate'], '%d.%m.%Y')) if 'country' in info.keys(): user['country'] = info['country']['title'] if 'sex' in info.keys(): user['gender'] = gender[info['sex']] if 'city' in info.keys(): user['city'] = info['city']['title'] if 'schools' in info.keys(): user['education'] = 'only_school' if info['schools']!=[]: if 'university' in info.keys(): if info['university']!=[]: user['education'] = 'school_and_uni' else: if 'university' in info.keys(): if info['university']!=[]: user['education'] = 'only_uni' else: if 'university' in info.keys(): user['education'] = 'only_uni' if 'personal' in info.keys(): if info['personal']!=[]: if 'political' in info['personal'].keys(): if info['personal']['political']>0: user['political'] = political_views[info['personal']['political']] if 'life_main' in info['personal'].keys(): if info['personal']['life_main']>0: user['life_views'] = life_views[info['personal']['life_main']] if 'people_main' in info['personal'].keys(): if info['personal']['people_main']>0: user['people_views'] = people_views[info['personal']['people_main']] if 'religion' in info['personal'].keys(): religion = info['personal']['religion'] if religion in religion_list.keys(): user['religion'] = religion_list[religion] else: user['religion'] = 'Другое' print(religion) return user
2. 给write_csv添加防御性检查
过滤列表中的None元素,同时处理空列表的情况:
def write_csv(listofdicts, filename): # 过滤无效的None元素 valid_dicts = [d for d in listofdicts if d is not None] if not valid_dicts: print("没有有效数据可写入CSV") return with open(filename, 'w') as csvFile: wr = csv.DictWriter(csvFile, fieldnames=valid_dicts[0].keys()) wr.writeheader() for el in valid_dicts: wr.writerow(el)
3. 优化create_dicts的异常处理
替换空except: pass,捕获具体异常并记录,方便排查问题:
def create_dicts(users_nowar, users_z, get_subs = True): user_list = [] startind = 0 users_nowar_info = [] while startind < len(users_nowar): stopind = min(startind+1000, len(users_nowar)) users_nowar_info += vk.users.get(user_ids = users_nowar[startind:stopind], fields = ['bdate','city','country', 'personal','sex','education','schools']) startind = stopind startind = 0 users_z_info = [] while startind < len(users_z): stopind = min(startind+1000, len(users_z)) users_z_info += vk.users.get(user_ids = users_z[startind:stopind], fields = ['bdate','city','country','personal', 'sex','education','schools']) startind = stopind for i in range(len(users_nowar)): clear_output(wait=True) print('nowar', i) try: user = create_dict_for_user(users_nowar[i], 'nowar', users_nowar_info[i], get_subs) if user is not None: user_list.append(user) else: print(f"用户{users_nowar[i]}生成字典失败") except Exception as e: print(f"处理用户{users_nowar[i]}时出错: {str(e)}") for i in range(len(users_z)): clear_output(wait=True) print('z', i) try: user = create_dict_for_user(users_z[i], 'z', users_z_info[i], get_subs) if user is not None: user_list.append(user) else: print(f"用户{users_z[i]}生成字典失败") except Exception as e: print(f"处理用户{users_z[i]}时出错: {str(e)}") return user_list
内容的提问来源于stack exchange,提问作者Alnur
相关产品推荐
相关产品推荐

