使用持久化按钮重启Discord Bot后出现函数调用错误
问题分析与修复方案
问题原因
重启Bot后点击持久化按钮报错'NoneType' object is not callable,核心原因是:
- 在
on_ready事件中,你添加了一个用genButton(command=None,channel=None)初始化的View实例用于持久化按钮同步。 - Bot重启后,Discord会将之前发送的按钮交互事件路由到这个
command为None的View实例上,此时执行self.command()自然会触发None不可调用的错误。 - 首次运行正常是因为当时点击的是通过
genEmbed命令发送的、传入了test函数的View实例,而非on_ready里的空参数实例。
修复方案
方案1:移除on_ready中带空参数的View添加,改为在View类中直接绑定固定函数
既然test是当前固定的生成Embed的函数,可以直接在View的按钮回调里调用它,不需要通过初始化参数传递:
class genButton(discord.ui.View): def __init__(self, channel): super().__init__(timeout=None) self.channel = channel @discord.ui.button(label="Generate",custom_id="gen_button",emoji=None,style=discord.ButtonStyle.success) async def generate(self, interaction: discord.Interaction, button: discord.ui.Button): embed = test() # 直接调用test函数 await interaction.response.send_message(embed=embed,ephemeral=True) # 修改on_ready中的View添加代码 @client.event async def on_ready(): try: synced = await client.tree.sync() print(f"Synced {len(synced)} commands") print(f"Active in {str(len(client.guilds))} servers") except Exception as e: print(e) try: client.add_view(genButton(channel=None)) # 只传channel,command不再需要 print("Synced buttons") except Exception as e: print(f"Failed to sync buttons {e}") # 修改genEmbed中的View实例化代码 await channel.send(embed=embed,view=genButton(channel))
方案2:在on_ready中添加View时传入正确的command参数
如果后续需要动态切换command函数,保持初始化传参的方式,只需要在on_ready里传入test而非None:
@client.event async def on_ready(): try: synced = await client.tree.sync() print(f"Synced {len(synced)} commands") print(f"Active in {str(len(client.guilds))} servers") except Exception as e: print(e) try: client.add_view(genButton(command=test,channel=None)) # 传入test函数 print("Synced buttons") except Exception as e: print(f"Failed to sync buttons {e}")
这样无论Bot重启前后,所有按钮交互都会使用带有有效command的View实例,避免None调用错误。
内容的提问来源于stack exchange,提问作者m_cr
相关产品推荐
相关产品推荐

