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

Discord.py触发AttributeError: 'NoneType' object has no attribute 'guild'如何修复

报错根因

这个AttributeError触发的原因是:当用户完全断开语音连接时,after.channel的值为None,此时直接访问after.channel.guild自然会抛出空对象无对应属性的异常。同时你的代码还有两处隐藏问题:

  • 逻辑判断顺序错误,没有优先处理用户离开语音的场景
  • 统计时长的代码里userdata[total_time]没有加引号,total_time会被识别为未定义变量,后续运行到这一步还会报错
修复后的完整代码
@commands.Cog.listener()
async def on_voice_state_update(self, member, before, after):
    if member.bot: # 优先检测是否为机器人,减少不必要的文件操作
        return
    with open('data/voice_leaderboard.json', 'r') as file: 
        voice_data = json.load(file)
    new_user = str(member.id)
    guild_id = str(member.guild.id)
    # 新增:新服务器防护,避免KeyError
    if guild_id not in voice_data:
        voice_data[guild_id] = {}
    if new_user not in voice_data[guild_id]: # 若用户不在当前服务器统计字典中则新增条目
        voice_data[guild_id][new_user] = {
            "total_time" : 0,
            "join_time" : None} 
    userdata = voice_data[guild_id][new_user] # 提取用户数据简化后续代码逻辑

    # 调整判断顺序:先处理加入频道场景
    if before.channel is None: 
        userdata["join_time"] = round(time.time())
    # 再处理完全离开频道场景
    elif after.channel is None:
        if userdata["join_time"] is None: 
            return
        # 统计本次语音时长
        leave_time = time.time()
        passed_time = leave_time - userdata["join_time"]
        # 修复:total_time改为字符串键
        userdata["total_time"] += passed_time
        userdata["join_time"] = None
    # 此时before、after的channel都非空,处理同服务器操作场景
    elif before.channel.guild.id == after.channel.guild.id:
        # 同服务器切换频道/调整静音等操作不修改计时,直接返回
        return
    # 剩余场景为跨服务器切换频道
    else:
        if userdata["join_time"] is None: 
            return
        leave_time = time.time()
        passed_time = leave_time - userdata["join_time"]
        userdata["total_time"] += passed_time
        userdata["join_time"] = None

    with open('data/voice_leaderboard.json', 'w') as update_user_data:
        json.dump(voice_data, update_user_data, indent=4)
关键改动说明
  • 调整了判断优先级,优先处理before.channel为None(加入)、after.channel为None(离开)的场景,避免后续判断时访问空对象的guild属性
  • 新增了服务器ID不存在于统计数据的防护逻辑,避免新服务器第一次触发事件时报KeyError
  • 修复了total_time未加引号的拼写错误
  • 所有空值判断改用is None的Python规范写法,避免隐式类型转换导致的逻辑错误

内容的提问来源于stack exchange,提问作者gwendal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:18:00