我是否在处理asyncio任务,而忽略了CancelledError?

时间:2019-02-14 10:39:01

标签: python python-asyncio

我不是问如何取消此类任务。这是不可能的,并在此处进行了说明: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时,我无法确定它是在第一次还是第二次超时时发生的。基本上我认为它可以,但是真的正确吗?

1 个答案:

答案 0 :(得分:1)

  

但是,如果我需要防御,该如何防止wait_for   无限地悬挂?

我认为不认为每个任务都可能无法取消是一个好主意。

通常,您只是假设不会发生这种情况,这是可以的,因为,是的,不可取消的任务是编程错误,而不是您希望经常看到的错误。通常,您不会期望某些内部代码会抑制KeyboardInterruptany other BaseException

期望第三方代码遵循某些合同是没有错的(例如上面的示例,或者说不是随机调用sys.exit())。否则,您将不得不编写很多的代码,并且可能仍然无法涵盖所有​​可能的情况。