bpo-29302: Implement contextlib.AsyncExitStack. by Kentzo · Pull Request #4790 · python/cpython (original) (raw)
@njsmith Good point regarding close() vs aclose() - I'd forgotten that part of PEP 525. Given that, I agree the method on AsyncExitStack should aclose(), and the synchronous close API should just be missing entirely (as with the other synchronous context management methods).
I'm not especially worried about folks having to sprinkle extra "async" mentions through their code to get async context managers to work as expected - that's the default language wide. For example, even though you've written stack = contextlib.AsyncExitStack()
, you also have to write async with stack:
- you can't just write with stack:
the way you can with the synchronous version and have Python automatically figure out you must have wanted to use the async variant of the with statement.
By contrast, I'm definitely not keen on having the correctness of code like f = stack.enter_context(open(file_of_interest))
depend on whether or not "stack" is a regular exit stack or an asynchronous one.
This does mean that stack.push(async_cm_or_exit)
and stack.callback(async_callback)
may run into the "coroutine never awaited" scenario, but that's why we have the other issue about detecting unawaited coroutines. I'd also be amenable to having a check (potentially __debug__
-only) in AsyncContextManager.__aexit__
itself for nominally synchronous callbacks returning awaitables, as that scenario is likely to inadvertently suppress exceptions as well (since a lot of awaitables are likely to be "True" by default).