Context manager protocol extension

I’ve already quoted @njs in the discussion about PEP 707 but I think his piece of insight is even more relevant for this discussion

So new users constantly try to write their own enter /exit methods […] and I think literally every person who’s ever tried this has gotten it wrong (mostly around exception handling details). At this point we don’t even try to debug; we just tell users to always use @contextmanager.

From a usability standpoint I think a single generator based __with__ inspired by @contextmanager instead of a pair of __enter__/__exit__ methods would be a clear usability improvement in addition to yielding (pun intended) a very natural syntax for a few features that the current context manager protocol lacks:

  • skipping the enclosed code block (already mentioned above)
  • accessing a value returned by the block from the context manager
def __with__(self):
    if some_condition:
        return  # early return means the enclosed block is skipped
    try:
        ...
        # binds 'self' to the name captured by the `as` clause 
        # and receives any value returned from the block 
        # into the variable 'block_return_value'
        block_return_value = yield self  
    except:
        ...
    else:
        ...  # potentially do stuff with 'block_return_value' here
    finally:
        ...
1 Like