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

如何在条件不满足时立即终止discord.py的wait_for()协程?

解决discord.py中wait_for无法随全局变量立即终止的问题

方案一:通过asyncio.wait同时监听消息与状态变化

全局变量cond修改后无法立即终止wait_for,是因为wait_for会一直阻塞直到收到符合条件的消息或超时。我们可以用asyncio.wait同时等待两个任务:监听消息的任务,以及持续检查cond状态的任务,只要其中一个完成就终止等待。

修改后的代码:

import asyncio

cond = True

@bot.command()
async def test(ctx):
    global cond

    def check(m):
        return m.author == ctx.author and m.channel == ctx.channel

    async def monitor_cond():
        while cond:
            await asyncio.sleep(0.5)
        return "cond_terminated"

    while cond:
        done, pending = await asyncio.wait(
            [bot.wait_for('message', check=check), monitor_cond()],
            return_when=asyncio.FIRST_COMPLETED
        )

        # 清理未完成的任务
        for task in pending:
            task.cancel()

        # 判断终止原因
        result = next(iter(done)).result()
        if result == "cond_terminated":
            break
        print('Message found!')

方案二:用asyncio.Event替代全局变量(推荐)

使用asyncio.Event比全局变量更适合异步场景,它支持原生的等待操作,无需轮询,可靠性更高。

代码示例:

import asyncio

stop_event = asyncio.Event()

@bot.command()
async def test(ctx):
    def check(m):
        return m.author == ctx.author and m.channel == ctx.channel

    stop_event.clear()  # 重置事件,确保每次命令执行初始状态正确
    while not stop_event.is_set():
        done, pending = await asyncio.wait(
            [bot.wait_for('message', check=check), stop_event.wait()],
            return_when=asyncio.FIRST_COMPLETED,
            timeout=7200
        )

        # 取消未完成任务
        for task in pending:
            task.cancel()

        for task in done:
            try:
                res = task.result()
                if res is None:  # stop_event.wait()触发时返回None
                    break
                print('Message found!')
            except asyncio.TimeoutError:
                print('No message was found.')

# 用于终止test命令的示例命令
@bot.command()
async def stop_test(ctx):
    stop_event.set()
    await ctx.send("Test命令已终止")

核心原理

两种方案都是利用asyncio.wait的FIRST_COMPLETED模式,让程序同时监听多个异步任务,只要其中一个任务完成(无论是收到消息、状态变化还是超时),就立即处理并终止其他任务,从而实现wait_for的即时终止。

内容的提问来源于stack exchange,提问作者Angel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:31:26