skip to Main Content

I have a queue which stored on Redis lists. I’m trying to create async consumer for this queue. But couldn’t call async function inside loop. Its working like sync function when I call.

import asyncio

async def worker():
    print("starting sleep")
    await asyncio.sleep(2)
    print("slept")

async def main():
    while True:
        await worker()

asyncio.run(main())

Here is a short and simple example of mine implemantation. I’m expecting to see ‘starting sleep’ messages until first ‘slept’ message, it means for 2 seconds.

2

Answers


  1. main is literally awaiting the completion of worker. Until worker is done, main won’t progress. async tasks don’t run in the background like in multithreading.

    What you want is to keep launching new workers without awaiting each one of them. However, if you just keep doing this in a loop like this:

    while True:
        worker()
    

    then you will never see any output of those workers, since this is an endless loop which never gives anything else the chance to run. You’d need to “break” this loop in some way to allow workers to progress. Here’s an example of that:

    import asyncio
    
    async def worker():
        print("starting sleep")
        await asyncio.sleep(2)
        print("slept")
    
    async def main():
        while True:
            asyncio.ensure_future(worker())
            await asyncio.sleep(0.5)
    
    asyncio.run(main())
    

    This will produce the expected outcome:

    starting sleep
    starting sleep
    starting sleep
    starting sleep
    slept
    starting sleep
    slept
    ...
    

    The await inside main transfers control back to the event loop, which now has the chance to run the piled up worker tasks, When those worker tasks await, they in turn transfer control back to the event loop, which will transfer it back to either main or a worker as their awaited sleep completes.

    Note that this is only for illustration purposes; if and when you interrupt this program, you’ll see notices about unawaited tasks which haven’t completed. You should keep track of your tasks and await them all to completion at the end somewhere.

    Login or Signup to reply.
  2. Here is an example using asyncio.wait:

    import asyncio
    
    async def worker():
        print("starting sleep")
        await asyncio.sleep(2)
        print("slept")
    
    async def main():
        tasks = [worker() for each in range(10)]
        await asyncio.wait(tasks)
    
    asyncio.run(main())
    

    It spawns all the workers together.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search