为什么 asyncio 任务的 done() 方法上的 while 循环会中断,即使条件逻辑始终为真?



我正在努力理解以下代码:

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())

日志:

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

3秒后,任务被取消,task.done()仍然为假,因此while循环从第15行继续……最后while循环在第16行中断并打印第22行。

请帮我解释一下为什么?我认为while循环应该永远运行,因为task.done()永远是false。

试着运行这个稍微修改过的代码版本:

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())

你可能会注意到输出现在是

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

这是因为您在3秒钟后呼叫task.cancel()。此调用成功取消了delay调用,但需要一段时间才能将任务的状态设置为"完成"。如果删除对task.cancel()的调用,while循环将运行您设置的整整5秒延迟。

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())

输出:

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

最新更新