Discord.py trainModal模态框异常忽略问题求助
Discord.py模态框提交后asyncio.sleep后续代码不执行,仅提示忽略异常
近期频繁遇到Discord.py报错:[modal.py] Ignoring exception in modal <trainModal timeout=None children=1>: (modal.py:164),该提示仅告知忽略异常,未提供具体错误详情,调试难度极大。
相关的trainModal类代码如下:
class trainModal(ui.Modal): def __init__(self): super().__init__( title="Training Dialog", ) self.amount = ui.TextInput(label="Amount", style=discord.TextStyle.short, placeholder="Integer", required=True, min_length=1) self.add_item(self.amount) async def on_submit(self, interaction): await interaction.response.defer() user = interaction.user val = int(self.amount.value) troop_name = train_select.values[0] troop_name = troop_name.lower() troop = Troops[troop_name] cost = troop["cost"] * val train_time = troop["time"] * val player = command_tree.db.get_player(user.id) if player.gold < cost: return await interaction.followup.send( f"You don't have enough gold to train {val} {troop_name}." ) msg: discord.WebhookMessage = await interaction.followup.send( f"Training {self.amount} {troop_name} in `{train_time}` seconds.") await asyncio.sleep(train_time) command_tree.db.update_player(user.id, +val, troop_name) command_tree.db.update_player(user.id, -cost, "gold") await msg.edit( content=f"Trained {self.amount} {troop_name} for {emote.GOLD} {cost}" )
代码逻辑为:用户通过模态框输入数值,提交后计算训练成本与时间,执行asyncio.sleep(train_time)等待训练完成,之后进行数据库更新与消息编辑。但sleep完成后代码从未执行,异常持续出现。
可能的问题点
- 异常无详细信息:modal.py默认忽略异常,无法定位具体错误,比如
train_select作用域问题、数据库操作出错、交互上下文失效等。 train_select作用域无效:直接使用train_select.values[0],若该变量未在on_submit方法作用域内定义或传递,会抛出NameError中断执行。- 交互上下文超时:
asyncio.sleep(train_time)会阻塞回调线程,若等待时间过长,Discord的交互上下文会失效,导致后续操作失败。 - 消息内容逻辑错误:用
self.amount拼接消息,self.amount是TextInput对象而非用户输入的数值,会导致消息显示异常。
解决方案
- 添加异常捕获,打印详细错误
在on_submit方法中加入try-except块,捕获并输出具体异常信息:
async def on_submit(self, interaction): try: await interaction.response.defer() user = interaction.user val = int(self.amount.value) troop_name = train_select.values[0] troop_name = troop_name.lower() troop = Troops[troop_name] cost = troop["cost"] * val train_time = troop["time"] * val player = command_tree.db.get_player(user.id) if player.gold < cost: return await interaction.followup.send( f"You don't have enough gold to train {val} {troop_name}." ) msg: discord.WebhookMessage = await interaction.followup.send( f"Training {val} {troop_name} in `{train_time}` seconds.") await asyncio.sleep(train_time) command_tree.db.update_player(user.id, +val, troop_name) command_tree.db.update_player(user.id, -cost, "gold") await msg.edit( content=f"Trained {val} {troop_name} for {emote.GOLD} {cost}" ) except Exception as e: print(f"模态框提交错误:{type(e).__name__} - {str(e)}") await interaction.followup.send(f"操作出错:{str(e)}", ephemeral=True)
- 确保
train_select作用域有效
将train_select通过构造函数传递给模态框:
class trainModal(ui.Modal): def __init__(self, train_select): super().__init__(title="Training Dialog") self.train_select = train_select self.amount = ui.TextInput(label="Amount", style=discord.TextStyle.short, placeholder="Integer", required=True, min_length=1) self.add_item(self.amount) async def on_submit(self, interaction): # ... 其他代码 troop_name = self.train_select.values[0].lower() # ... 其他代码
- 改用异步任务处理等待逻辑
避免阻塞事件循环,用asyncio.create_task将等待和后续操作放入异步任务:
async def process_training(interaction, user, val, troop_name, cost, train_time, msg): await asyncio.sleep(train_time) command_tree.db.update_player(user.id, +val, troop_name) command_tree.db.update_player(user.id, -cost, "gold") await msg.edit( content=f"Trained {val} {troop_name} for {emote.GOLD} {cost}" ) async def on_submit(self, interaction): await interaction.response.defer() user = interaction.user val = int(self.amount.value) troop_name = train_select.values[0].lower() troop = Troops[troop_name] cost = troop["cost"] * val train_time = troop["time"] * val player = command_tree.db.get_player(user.id) if player.gold < cost: return await interaction.followup.send( f"You don't have enough gold to train {val} {troop_name}." ) msg = await interaction.followup.send( f"Training {val} {troop_name} in `{train_time}` seconds.") asyncio.create_task(process_training(interaction, user, val, troop_name, cost, train_time, msg))
- 修正消息中的数值引用
将self.amount替换为val,确保显示用户输入的数值:
# 修正前 # f"Training {self.amount} {troop_name} in `{train_time}` seconds." # 修正后 f"Training {val} {troop_name} in `{train_time}` seconds."
内容的提问来源于stack exchange,提问作者user18323078
相关产品推荐
相关产品推荐

