python - 取消异步上下文管理器

标签 python python-asyncio

获取要取消的任务的句柄非常容易:

task = loop.create_task(coro_fn())

# later
task.cancel()

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

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

# later
# How do I get a handle to the context manager for cancellation?

有什么办法可以做到这一点吗?或者上下文管理器代码是否需要在自己的任务中运行?

最佳答案

How do I get a handle to the context manager for cancellation?

你不知道,至少不直接知道 - 上下文管理器只是获取和释放资源的方法的方便包装。您的问题中的 async with foo() as bar: ... 大致如下:

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

__aenter____aexit__都是普通的awaitable,其执行可以被取消,就像await bar.baz的执行一样()async with 主体内。

因此,如果“取消上下文管理器”是指取消 async with block 当前陷入的操作,则可以像任何其他取消一样执行此操作。例如,您可以将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

关于python - 取消异步上下文管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55551164/

相关文章:

python - 我可以使用 asyncio 读取和写入 multiprocessing.Pipe 吗?

python - 异步队列在与后台线程一起使用时挂起

python - 可取消的 Asyncio 键盘输入

Python 3.4 asyncio 任务没有完全执行

python - mkdir(名称,模式)OSError

python - 用 python 自动化 firefox?

Python多线程用于同时输入和套接字连接

python - 在 Kivy 中使用 RecycleView 的自定义小部件的对齐问题

python - 强制解包某些 egg 目录

python - 通过 ElementTree 附加和格式化新的子元素