【问题标题】:Discord.py - Asyncio Timeout not working properlyDiscord.py - Asyncio 超时无法正常工作
【发布时间】:2021-05-23 14:07:07
【问题描述】:

预期的输出和我的代码是什么:

我的机器人应该发送一条消息,然后检查发送命令的用户是否对该消息做出了反应,:arrow_left::arrow_right::wastebasket:,如果他们这样做了,它应该更改消息的“页面”。这部分工作正常,但我也希望消息在 7 秒不活动后超时。

        embed = await self.get_member_list(ctx, member, page)

        msg = await ctx.send(embed=embed)

        reactions = ["⬅️", "➡️", "????️"]
        for x in r:
            await msg.add_reaction(x)
            await asyncio.sleep(.35)

        def check(payload):
            return str(payload.emoji) in reactions

        done = False
        page = 1
        while not done:
            try:
                pending_tasks = [self.bot.wait_for('raw_reaction_add', timeout=7.0, check=check),
                                 self.bot.wait_for('raw_reaction_remove', timeout=7.0, check=check)]

                done_tasks, pending_tasks = await asyncio.wait(pending_tasks, return_when=asyncio.FIRST_COMPLETED)

                for task in done_tasks: payload = await task
                user = await commands.MemberConverter().convert(ctx, str(payload.user_id))

            except asyncio.TimeoutError:
                done = True
                return
            else:
                if user == ctx.author:
                    if str(payload.emoji) == "????️":
                        return await msg.delete(delay=0)
                    if str(payload.emoji) == "⬅️":
                        if page == 1:
                            page = total_pages
                        else:
                            page -= 1
                    if str(payload.emoji) == "➡️":
                        if page == total_pages:
                            page = 1
                        else:
                            page += 1
                    await msg.edit(embed=await self.get_member_list(ctx, member, page)) # 

但是,运行上述代码后,我遇到了“从未检索到任务异常”的问题。

实际结果:

Task exception was never retrieved
future: <Task finished name='Task-58' coro=<wait_for() done, defined at C:\Users\AppData\Local\Programs\Python\Python38\lib\asyncio\tasks.py:434> exception=TimeoutError()>
Traceback (most recent call last):
  File "C:\Users\AppData\Local\Programs\Python\Python38\lib\asyncio\tasks.py", line 501, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

问题:

每当 7 秒的不活动时间过去并且它应该超时时,我都会收到错误消息。我试图通过运行 asyncio.gather() 来解决这个问题,但我不熟悉 asyncio,我不确定如何正确使用它。

done_tasks, pending_tasks = await asyncio.wait(pending_tasks, return_when=asyncio.FIRST_COMPLETED)
await asyncio.gather('raw_reaction_add', 'raw_reaction_remove', return_exceptions=True)

我试过了:

  • 检查错别字

  • 运行 except Exceptionexcept asyncio.exceptions.TimeoutError 而不是 except asyncio.TimeoutError

  • 考虑我的理智

  • 读取 asyncio documentation,特别是在 asyncio.wait()

  • 确保我的机器人在不和谐中拥有它需要的所有权限和意图

  • 在元组中使用 self.bot.wait_for() 和 raw_reaction_add 和 raw_reaction_remove 代替 asyncio.wait()

【问题讨论】:

  • 只使用一个事件而不使用asyncio.wait 是否有效?
  • @Ceres 是的。

标签: python-3.x discord.py


【解决方案1】:

我最终通过这样做摆脱了错误消息:

首先我将超时从bot.wait_for() 移到asyncio.wait()

pending_tasks = [self.bot.wait_for('raw_reaction_add', check=check),
                 self.bot.wait_for('raw_reaction_remove', check=check)]

                done_tasks, pending_tasks = await asyncio.wait(pending_tasks, timeout=7.0, return_when=asyncio.FIRST_COMPLETED)

然后我从弹出窗口而不是等待任务中获取有效负载

payload = done_tasks.pop().result()

现在在 7 秒不活动后,它会尝试从一个空集合中弹出并引发一个 KeyError,我可以使用 except KeyError: 捕获它

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 2021-08-29
    • 2020-09-25
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 2014-11-30
    • 1970-01-01
    相关资源
    最近更新 更多