Discord.py实现自定义help命令循环编辑消息时help_msg变NoneType报错
问题根因
报错的核心原因是错误地将Message.edit()方法的返回值重新赋值给了help_msg变量,触发逻辑完全匹配你描述的报错时机:
- 你使用的discord.py版本(多为老版Async分支v0.16.x)中,
Message.edit()方法没有显式返回值,调用后默认返回None - 循环第一次处理help命令条目时:
- 此时
help_msg还是ctx.send()返回的有效消息对象,能正常调用edit()完成第一次内容编辑 - 但编辑完成后,代码将
edit()的返回值(也就是None)重新赋值给help_msg,直接覆盖了原来持有的有效消息对象引用
- 此时
- 循环第二次处理ping命令条目时,尝试调用
help_msg.edit(),但此时help_msg已经是被覆盖后的NoneType对象,直接抛出对应属性错误
简单说:你本来想通过edit的返回值更新消息引用,但老版本的edit根本不返回消息对象,直接把你的有效引用冲没了。
其他隐患点
@bot.command(pass_context=True)是discord.py v1.0之前的老写法,这个参数早在版本迭代中就被移除了,现在调用命令时会自动传入ctx参数,保留这个参数反而会触发装饰器报错- 逐次编辑消息的写法会多次和Discord API交互,很容易触发速率限制,完全可以先把所有命令说明拼接成完整字符串,一次性发送或编辑完成,减少不必要的请求
- 现有代码没有对消息字符长度做校验,后续如果命令多了,很容易超出Discord单条消息2000字符的上限
修复方法
- 去掉循环里对
edit()返回值的重新赋值——help_msg本身就是你要编辑的目标消息实例,edit()调用后会自动更新实例内部的content属性,根本不需要接收返回值
错误写法:
修改后的写法:help_msg = await help_msg.edit(content=str(help_msg.content)+commande+info)await help_msg.edit(content=str(help_msg.content)+commande+info) - 去掉ping命令装饰器里多余的
pass_context=True参数 - 可选优化:提前拼接好完整的帮助文档内容,一次性发送,避免多次编辑:
@bot.command(aliases = ['h','aide']) async def help(ctx): full_content = "__**Available commands:**__" for commande, info in help_list.items(): full_content += commande + info await ctx.send(full_content)
内容的提问来源于stack exchange,提问作者nwcubeok
相关产品推荐
相关产品推荐

