[Python-ideas] Relax __exit__ method to be a generator

Guido van Rossum guido at python.org
Mon Apr 7 01:12:51 CEST 2014


I prefer to use a try/finally statement. One of the points of using
yield-from is that you can always tell where your code may be suspended by
searching for "yield from". With your proposed change that would no longer
be true -- any with statement would also have to be inspected, and there
would no longer be a way to know from the source alone whether it might
yield or not (because it would dynamic -- there's no way to be sure at
compile time which context manager is being used).


On Sun, Apr 6, 2014 at 12:02 PM, Andrew Svetlov <andrew.svetlov at gmail.com>wrote:

> Literally it may be generator itself or function that returns generator
> object.
>
> Now I'm working on postgres library for asyncio (
> http://aiopg.readthedocs.org/).
>
> And I would to use *with statement* for transaction handling like:
>
> with (yield from cursor.transaction()):
>    yield from cursor.execute(sql)
>
> The problem is: at exit of *with statement* I need to call `yield from
> cursor.execute('COMMIT')` or `yield from cursor.execute('ROLLBACK')`.
>
> I can do it only in __exit__ in *context manager*, but python
> understand only if __exit__:
> - returns true value, that suppresses exception from code block
> - returns None or any false value to propagate exception if any
> - raises exception itself
>
> I propose to add new rule:
> IF the code object is generator (co_flags & CO_GENERATOR) and __exit__
> returns generator object (isinstance(ret, types.GeneratorType))
> THEN do `yield from ret`.
>
> That's work fine if __exit__ itself is a *generator function*
> (contains `yield` or `yield from` statements): call to *generator
> function* returns *generator object*.
>
> The proposal:
> 1. Doesn't break any existing code except if user accidentally
> returns generator object instead of True from __exit__ call (he should
> not to do this and I sure this is very rare case).
> 2. Don't requires new syntax.
>
> asyncio itself uses:
>
> with (yield from lock):
>    BLOCK
>
> for locking etc but unlocking for asyncio objects doesn't requires any
> `yield from`, so __exit__ code is just plain function but not
> generator.
>
> Also I can live with asyncio trick for __enter__:
> https://code.google.com/p/tulip/source/browse/asyncio/locks.py#156
> The way is a but annoying but unrolling a value returned by __enter__
> if the value is generator object will break existing code, sure.
>
> Thoughts?
>
>
> --
> Thanks,
> Andrew Svetlov
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20140406/3f8cb251/attachment-0001.html>


More information about the Python-ideas mailing list