Skip to content
Advertisement

How to terminate wait_for() when a condition is no longer met?

My discord.py command for a bot is supposed to activate a while loop under the condition that a specific variable has a certain value (with a wait_for() coroutine within it):

cond = True

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

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

    while cond is True: 
        try:
            msg = await bot.wait_for('message', check=check, timeout=7200) # 2 hours
            print('Message found!')

        except asyncio.TimeoutError:
            print('No message was found.')

It only executes while cond is True, however cond can change while wait_for() is running (I used a global variable for the example), and since this is a while loop it doesn’t terminate during runtime if the condition is no longer met, rather it applies to the next iteration.

I want wait_for() immediately terminate soon as cond is no longer True, and any code following to not execute (including the except block). Alternatively the while loop could be terminated some way while wait_for() is running.

How can I achieve this?

Advertisement

Answer

We know that wait_for immediatly terminates when its condition is met. We can use this to just add the loop condition into the wait_for condition as follows:

(wait_for condition) or not (loop condition)

The if the loop condition does no longer hold, we exit the wait_for. After we exit we also have to check if we exited the wait_for because of the loop condition or the actual thing we’re waiting for. We only actually execute the code if it’s the former.

Hence you can rewrite the code as follows:

cond = True

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

    def check(m):
        (m.author == ctx.message.author and m.channel == ctx.message.channel) or not cond

    while cond is True: 
        try:
            msg = await bot.wait_for('message', check=check, timeout=7200) # 2 hours       
            if (cond):
                # we only want to continue here if the loop condition still holds
                print('Message found!')

        except asyncio.TimeoutError:
            print('No message was found.')
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement