Как получить дескриптор диспетчера контекста для отмены?
Вы, по крайней мере, не напрямую, - менеджер контекста - это просто удобная упаковка для методов получения и освобождения ресурса. async with foo() as bar: ...
от вашего вопроса desugars к чему-то вроде:
_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