Home > database >  Use asyncio.all_tasks() in the right place
Use asyncio.all_tasks() in the right place

Time:10-06

I am reading the book and face the code snippet, which doesn't makes sense for me. Can someone clarify that for me ?

import asyncio

async def main():
    print(f'{time.ctime()} Hello!')
    await asyncio.sleep(1.0)
    print(f'{time.ctime()} Goodbye!')


loop = asyncio.get_event_loop()
task = loop.create_task(main())
loop.run_until_complete(task) # This line is responsible to block the thread (Which is MainThread in my case), until every coroutine won't be finished.
pending = asyncio.all_tasks(loop=loop) # asyncio.all_tasks() Return a set of not yet finished Task objects run by the loop. Based on definition, pending will always be an empty set.
for task in pending:
    task.cancel()
group = asyncio.gather(*pending, return_exceptions=True)
loop.run_until_complete(group)
loop.close()

I think asyncio.all_tasks() should be used before loop.run_until_complete() function. Besides I find many other places where it is useful, but this example absolutely does not makes sense for me. I am really interested in, why author did that ? What was the point ?

CodePudding user response:

What you are thinking is correct. There is no point here for having .all_tasks() as it always returns an empty set. You only have one task and you pass it to .run_until_complete(), so it blocks until it gets done.

But things change when you have another task that takes longer than your main coroutine:

import asyncio
import time


async def longer_task():
    print("inside longer coroutine")
    await asyncio.sleep(2)


async def main():
    print(f"{time.ctime()} Hello!")
    await asyncio.sleep(1.0)
    print(f"{time.ctime()} Goodbye!")


loop = asyncio.new_event_loop()
task1 = loop.create_task(main())
task2 = loop.create_task(longer_task())

loop.run_until_complete(task1)

pending = asyncio.all_tasks(loop=loop)
print(pending)
for task in pending:
    task.cancel()
group = asyncio.gather(*pending, return_exceptions=True)
loop.run_until_complete(group)
loop.close()

Event loop only cares to finish task1 so task2 is gonna be in pending mode.

I think asyncio.all_tasks() should be used before loop.run_until_complete() function.

As soon as you create_task(), it will be included in the set returned by all_tasks() even if the loop has not started yet.

Just a side note: (version 3.10) Since you don't have a running event loop, .get_event_loop() will warn you. use .new_event_loop() instead.

  • Related