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

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对象而非用户输入的数值,会导致消息显示异常。

解决方案

  1. 添加异常捕获,打印详细错误
    在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)
  1. 确保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()
        # ... 其他代码
  1. 改用异步任务处理等待逻辑
    避免阻塞事件循环,用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))
  1. 修正消息中的数值引用
    将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:42:47