Search code examples
pythonasynchronousasync-awaitpython-asyncio

Are there any ways to actually stop awaited long-running asyncio Task?


If there is a long-running background task, cancel() method does not work as I expected (does not work at all). And I cannot find a way to actually stop the task, is that even possible or am I missing something about asyncio work?

Documentation says: "Task.cancel() does not guarantee that the Task will be cancelled."

But as far as I understand it is due to possibility of coroutine handling the CancelledError exception and suppressing cancelation which is not my case.

I tried to run sample code beneath and got infinite loop running forever, cancel() there does not work.
My understanding here is that hitting that await asyncio.sleep(1) on the next asyncio event loop iteration should trigger task cancellation, but it is not happening.
How can I make already awaited background_task stop?

async def background_task():
    while True:
        print('doing something')
        await asyncio.sleep(1)


async def main():
    task = asyncio.create_task(background_task())
    await task
    task.cancel()
    print('Done!')


asyncio.run(main())

The output would be:

doing something
doing something
doing something
doing something
doing something
doing something
...

Solution

  • Turns out its not possible in my case. If you await a long-running task - the caller will wait for task completion and therefore block (thanks to @mkrieger1 for the explanation in comments). To actually stop the task, you should either modify it and add some event or flag like @zShadowSkilled mentioned, or run it with asyncio.wait_for() by specifying a timeout.