我不是问如何取消此类任务。这是不可能的,并在此处进行了说明:https://stackoverflow.com/a/33578893/5378816
我担心的是wait_for中的这一变化:
在3.7版中进行了更改:当aw由于超时而被取消时, wait_for等待aw被取消。以前,它提出 立即出现asyncio.TimeoutError。
别误会我,我喜欢它,这是一种进步。
但是,此程序现在将挂在wait_for
(Python 3.7)中:
import asyncio
async def uncancellable():
while True:
try:
await asyncio.sleep(99)
except asyncio.CancelledError:
print("sorry!")
TIMEOUT = 1.0
async def test():
task = asyncio.get_event_loop().create_task(uncancellable())
try:
await asyncio.wait_for(task, TIMEOUT)
except asyncio.TimeoutError:
print("timeout")
asyncio.get_event_loop().run_until_complete(test())
不可取消的任务是编程错误。但是,如果我需要成为defensive,如何防止wait_for
无限期挂起?
我尝试过了。第一次超时:取消之前,第二次超时:放弃之前。
await asyncio.wait_for(asyncio.wait_for(task, TIMEOUT1), TIMEOUT1+TIMEOUT2)
我不关心一个小问题。当它提高asyncio.TimeoutError
时,我无法确定它是在第一次还是第二次超时时发生的。基本上我认为它可以,但是真的正确吗?
答案 0 :(得分:1)
但是,如果我需要防御,该如何防止wait_for 无限地悬挂?
我认为不认为每个任务都可能无法取消是一个好主意。
通常,您只是假设不会发生这种情况,这是可以的,因为,是的,不可取消的任务是编程错误,而不是您希望经常看到的错误。通常,您不会期望某些内部代码会抑制KeyboardInterrupt
或any other BaseException
。
期望第三方代码遵循某些合同是没有错的(例如上面的示例,或者说不是随机调用sys.exit()
)。否则,您将不得不编写很多的代码,并且可能仍然无法涵盖所有可能的情况。