You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因与解决方法

核心原因

  1. create_dict_for_user函数中,当get_subs=False时,没有定义user字典的代码块,函数默认返回None,导致create_dicts生成的列表中混入None元素。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:59:54