'Python Discord Bot await commands finishing too late

I am creating a discord bot. It is meant to receive files, and then run an executable. Right now I have the users send the files in a message, then type "done" to let it know they're finished. However, if the users type "done" in the same message they attached the files to, the function that saves them to disk runs after the main thread continues on. I thought that await would cause this to happen afterwards.

Here is the code:

async def download(msg):
    for attachment in msg.attachments:
        await attachment.save(attachment.filename)
        shutil.move(attachment.filename, "./mons")
        global numattach
        numattach += 1
        print(f"File added! Numattach = {numattach}")

async def delete(msg):
    await msg.delete()

def check(msg):

    if(limitChannel) and (msg.channel.id == channelId):
        if msg.author.bot:
            return False
        if msg.author.id == ctx.author.id and "done" in msg.content:
            asyncio.create_task(download(msg))
            #thread = threading.Thread(target=asyncio.run, args=(download(msg),))
            #thread.start()
            #thread.join()
            asyncio.create_task(delete(msg))
            return True
        elif msg.author.id == ctx.author.id:
            asyncio.create_task(download(msg))
            asyncio.create_task(delete(msg))
            return False
    else:
        return False

async def trying(ctx):
    try:
        ctx = await client.wait_for("message", check=check, timeout=60)
    except asyncio.TimeoutError:
        await ctx.channel.send(content=f"YOU HATH WAITED TOO LONG, {user}!")
        global readyforcommand
        readyforcommand = True
    return ctx

await ctx.channel.send(f"SEND ME YOUR FILES, {ctx.author.mention}! Type done when done!")

ctx = await trying(ctx)  

global numattach
print(f"Number of files received: {numattach}")
if numattach < 2 or numattach > 4:
    await ctx.channel.send("Error: You need to attach 2 - 4 files to find a valid seed.")
    readyforcommand = True
    await ctx.channel.send(f"I HATH FINISHED WITH {user}'s SEED. I SHALT NOW MOVE ON.")
    return

await run_etumrepseed(ctx)

Does anyone know how I can fix this so that in that one case, it won't finish early? Every time I test, I see that numattach = 0 when it gets to that part of the code where it checks how many attachments there were, then I see the download(msg) function run, and set numattach to 2 - 4.



Solution 1:[1]

I think the problem there is that your check functions return True when the users type "done" in the same message they attached the files to. In this case the wait_for was fulfilled and it continues the main execution. The reason it happens is pretty much the following: you are using create_task which schedules it to run in the background in a non-blocking way. In order to ensure the completion you might want to await your tasks before returning True in the check function or by using asyncio.gather to which you can pass all the tasks and it'll suspect the function execution until all tasks are completed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Oleksandr Motornyi