取消异步上下文管理器

时间:2019-04-06 16:37:51

标签: python python-asyncio

很容易获得取消任务的句柄:

this

是否可以对异步上下文管理器执行相同的操作?

module.exports

有没有办法做到这一点?还是上下文管理器代码需要在自己的任务中运行?

1 个答案:

答案 0 :(得分:3)

  

如何获得上下文管理器的取消处理?

您不会,至少不是直接-上下文管理器只是一种用于获取和释放资源的方法的便捷包装。您问题中的async with foo() as bar: ...可能会变成类似以下内容:

_cm = foo()
bar = await _cm.__aenter__()
try:
    await bar.baz()
finally:
    await _cm.__aexit__(*sys.exc_info())

__aenter____aexit__都是正常的等待对象,可以取消其执行,就像在await bar.baz()正文中执行async with一样

因此,如果通过“取消上下文管理器”来表示取消async with块当前停留的操作,则可以执行与其他任何取消操作相同的操作。例如,您可以将async with提取到在自己的任务中运行的协程中,然后cancel()进行运行。请注意,无论如何您都需要获得一个任务,甚至要到达“以后”部分,而异步上下文管理器不会在该过程中关闭。

这里是一个例子:

async def run_foo():
    async with foo() as bar:
       # is it possible to cancel before getting here,
       # while waiting to enter the context manager?
       await bar.baz()

task = asyncio.create_task(run_foo())
# "task" is the handle you can await or cancel at your leisure