[Python-ideas] Yielding through context managers

Nick Coghlan ncoghlan at gmail.com
Tue Jan 8 11:13:50 CET 2013


On Tue, Jan 8, 2013 at 11:06 AM, Guido van Rossum <guido at python.org> wrote:
> On Sun, Jan 6, 2013 at 9:47 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> Ah, true, I hadn't thought of that. So yes, any case where the
>> __exit__ method can be "fire-and-forget" is also straightforward to
>> implement with just PEP 3156. That takes us back to things like
>> database transactions being the only ones where
>
> And 'yielding' wouldn't do anything about this, would it?

Any new syntax should properly handle the database transaction context
manager problem, otherwise what's the point? The workarounds for
asynchronous __next__ and __enter__ methods aren't too bad - it's
allowing asynchronous __exit__ methods that can only be solved with
new syntax.

>> I'm not seeing any obvious holes in that strategy, but I haven't
>> looked closely at the compiler code in a while, so there may be
>> limitations I haven't accounted for.
>
> So would 'yielding' insert the equivalent of 'yield from' or the
> equivalent of 'yield' in the code?

Given PEP 3156, the most logical would be for it to use "yield from",
since that is becoming the asynchronous equivalent of a normal
function call.

Something like:

    with yielding db.session() as :
        # Do stuff here

Could be made roughly equivalent to:

    _async_cm = db.session()
    conn = yield from _async_cm.__enter__()
    try:
        # Use session here
    except Exception as exc:
        # Rollback
        yield from _async_cm.__exit__(type(exc), exc, exc.__traceback__)
    else:
        # Commit
        yield from _async_cm.__exit__(None, None, None)

Creating a contextlib.contextmanager style decorator for writing such
asynchronous context managers would be difficult, though, as the two
different meanings of "yield" would get in each other's way - you
would need something like "yield EnterResult(expr)" to indicate to
__enter__ in the wrapper object when to stop. It would probably be
easier to just write separate __enter__ and __exit__ methods as
coroutines.

However, note that I just wanted to be clear that I consider the idea
of a syntax for "asynchronous context managers" plausible, and
sketched out a possible design to explain *why* I thought it should be
possible. My focus will stay with PEP 432 until that's done.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list