Search code examples
pythonpython-asynciopython-3.7producer-consumerfire-and-forget

Fire, Forget, and Return Value in Python3.7


I have the following scenario: I have a python server that upon receiving a request, needs to parse some information, return the result to the user as quickly as possible, and then clean up after itself. I tried to design it using the following logic:

Consumer: *==*   (wait for result)   *====(continue running)=====...
              \                     / return
Producer:      *======(prase)====*=*
                                  \
Cleanup:                           *==========*

I've been trying to use async tasks and coroutines to make this scenario work with no avail. Everything I tried ends up with either the producer waiting for the cleanup to finish before returning, or the return killing the cleanup. I could in theory have the consumer call the cleanup after it displays the result to the user, but I refuse to believe Python doesn't know how to "fire-and-forget" and return.

For example, this code:

import asyncio

async def Slowpoke():
    print("I see you shiver with antici...")
    await asyncio.sleep(3)
    print("...pation!")

async def main():
    task = asyncio.create_task(Slowpoke())
    return "Hi!"

if __name__ == "__main__":
    print(asyncio.run(main()))
    while True:
        pass

returns:

I see you shiver with antici...
Hi!

and never gets to ...pation.

What am I missing?


Solution

  • I managed to get it working using threading instead of asyncio:

    import threading
    import time
    
    def Slowpoke():
        print("I see you shiver with antici...")
        time.sleep(3)
        print("...pation")
    
    def Rocky():
        t = threading.Thread(name="thread", target=Slowpoke)
        t.setDaemon(True)
        t.start()
        time.sleep(1)
        return "HI!"
    
    if __name__ == "__main__":
        print(Rocky())
        while True:
            time.sleep(1)