Issue
I'm trying to understand this code:
async def delay(sec: int):
print(f"delay() going to sleep for {sec}s")
await asyncio.sleep(sec)
print("delay() waked up")
async def main():
task = asyncio.create_task(delay(5))
seconds_elapsed = 0
while not task.done():
print(f"checking task finished... {task.done()}")
await asyncio.sleep(1)
seconds_elapsed += 1
if seconds_elapsed == 3:
print(f"cancelled result: {task.cancel()}")
print(f"task is done: {task.done()}")
print("main() awaiting task")
try:
# await task
pass
except asyncio.CancelledError:
print("task was cancelled")
print("main() finished")
asyncio.run(main())
The logs:
checking task finished... False
delay() going to sleep for 5s
checking task finished... False
checking task finished... False
cancelled result: True
task is done: False
checking task finished... False
main() awaiting task
main() finished
After 3s has passed, the task was canceled and the task.done()
is still false, so the while
loop continues with line 15... finally the while loop break at line 16 and print line 22.
Pls help me to explain why? I thought that the while loop should run forever because the task.done()
will always be false.
Solution
Try running this slightly modified version of your code:
import asyncio
async def delay(sec: int):
print(f"delay() going to sleep for {sec}s")
await asyncio.sleep(sec)
print("delay() waked up")
async def main():
task = asyncio.create_task(delay(5))
seconds_elapsed = 0
while not task.done():
print(f"checking task finished... {task.done()}")
await asyncio.sleep(1)
seconds_elapsed += 1
if seconds_elapsed == 3:
print(f"cancelled result: {task.cancel()}")
print(f"task is done: {task.done()}")
print(f"Check task again: {task.done()}")
print("main() awaiting task")
try:
# await task
pass
except asyncio.CancelledError:
print("task was cancelled")
print("main() finished")
asyncio.run(main())
You may notice that the output is now
checking task finished... False
delay() going to sleep for 5s
Check task again: False
checking task finished... False
Check task again: False
checking task finished... False
cancelled result: True
task is done: False
Check task again: False
checking task finished... False
Check task again: True # Look here!!!
main() awaiting task
main() finished
This is because you are calling task.cancel()
after 3 seconds. This call successfully cancels the delay
call, but it takes a moment for the status of the task to be set to done. If you remove the call to task.cancel()
the while loop will run for the full 5 second delay you set.
import asyncio
async def delay(sec: int):
print(f"delay() going to sleep for {sec}s")
await asyncio.sleep(sec)
print("delay() waked up")
async def main():
task = asyncio.create_task(delay(5))
seconds_elapsed = 0
while not task.done():
print(f"checking task finished... {task.done()}")
await asyncio.sleep(1)
seconds_elapsed += 1
if seconds_elapsed == 3:
print(f"task is done: {task.done()}")
print("main() awaiting task")
try:
# await task
pass
except asyncio.CancelledError:
print("task was cancelled")
print("main() finished")
asyncio.run(main())
Output:
checking task finished... False
delay() going to sleep for 5s
checking task finished... False
checking task finished... False
task is done: False
checking task finished... False
checking task finished... False
delay() waked up
main() awaiting task
main() finished
Answered By - JRose
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.