<div dir="ltr">Well, for new syntax, the bar is pretty high... And we should probably move to python-ideas.<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Apr 6, 2014 at 4:44 PM, Andrew Svetlov <span dir="ltr"><<a href="mailto:andrew.svetlov@gmail.com" target="_blank">andrew.svetlov@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Well, this is good point..<br>
<br>
But from my experience try/finally is a common point of errors.<br>
Beginners use "with" properly as:<br>
<br>
with open(filename) as f:<br>
f.read()<br>
<br>
but switch to try/finally produces very common error.<br>
<br>
Instead of<br>
<br>
f = open(filename)<br>
try:<br>
f.read()<br>
finally:<br>
f.close()<br>
<br>
people usually write<br>
<br>
try:<br>
f = open(filename)<br>
f.read()<br>
finally:<br>
f.close()<br>
<br>
I saw it constantly many times. When I wrote an article about the<br>
problem and true solution in my blog I got several emails from my<br>
readers: please, tell me again why I need to move open() out of try<br>
block if it can generate exception on file opening?<br>
<br>
So maybe you would like some other syntax? For example<br>
<br>
with from obj:<br>
BLOCK<br>
<br>
That form can use magic methods with names different than<br>
__enter__/__exit__ (and get rid of "with (yield from lock)" BTW). And<br>
it's obviously? points on two suspending points: at BLOCK enter and<br>
exit.<br>
<div class="HOEnZb"><div class="h5"><br>
On Mon, Apr 7, 2014 at 2:12 AM, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
> I prefer to use a try/finally statement. One of the points of using<br>
> yield-from is that you can always tell where your code may be suspended by<br>
> searching for "yield from". With your proposed change that would no longer<br>
> be true -- any with statement would also have to be inspected, and there<br>
> would no longer be a way to know from the source alone whether it might<br>
> yield or not (because it would dynamic -- there's no way to be sure at<br>
> compile time which context manager is being used).<br>
><br>
><br>
> On Sun, Apr 6, 2014 at 12:02 PM, Andrew Svetlov <<a href="mailto:andrew.svetlov@gmail.com">andrew.svetlov@gmail.com</a>><br>
> wrote:<br>
>><br>
>> Literally it may be generator itself or function that returns generator<br>
>> object.<br>
>><br>
>> Now I'm working on postgres library for asyncio<br>
>> (<a href="http://aiopg.readthedocs.org/" target="_blank">http://aiopg.readthedocs.org/</a>).<br>
>><br>
>> And I would to use *with statement* for transaction handling like:<br>
>><br>
>> with (yield from cursor.transaction()):<br>
>> yield from cursor.execute(sql)<br>
>><br>
>> The problem is: at exit of *with statement* I need to call `yield from<br>
>> cursor.execute('COMMIT')` or `yield from cursor.execute('ROLLBACK')`.<br>
>><br>
>> I can do it only in __exit__ in *context manager*, but python<br>
>> understand only if __exit__:<br>
>> - returns true value, that suppresses exception from code block<br>
>> - returns None or any false value to propagate exception if any<br>
>> - raises exception itself<br>
>><br>
>> I propose to add new rule:<br>
>> IF the code object is generator (co_flags & CO_GENERATOR) and __exit__<br>
>> returns generator object (isinstance(ret, types.GeneratorType))<br>
>> THEN do `yield from ret`.<br>
>><br>
>> That's work fine if __exit__ itself is a *generator function*<br>
>> (contains `yield` or `yield from` statements): call to *generator<br>
>> function* returns *generator object*.<br>
>><br>
>> The proposal:<br>
>> 1. Doesn't break any existing code except if user accidentally<br>
>> returns generator object instead of True from __exit__ call (he should<br>
>> not to do this and I sure this is very rare case).<br>
>> 2. Don't requires new syntax.<br>
>><br>
>> asyncio itself uses:<br>
>><br>
>> with (yield from lock):<br>
>> BLOCK<br>
>><br>
>> for locking etc but unlocking for asyncio objects doesn't requires any<br>
>> `yield from`, so __exit__ code is just plain function but not<br>
>> generator.<br>
>><br>
>> Also I can live with asyncio trick for __enter__:<br>
>> <a href="https://code.google.com/p/tulip/source/browse/asyncio/locks.py#156" target="_blank">https://code.google.com/p/tulip/source/browse/asyncio/locks.py#156</a><br>
>> The way is a but annoying but unrolling a value returned by __enter__<br>
>> if the value is generator object will break existing code, sure.<br>
>><br>
>> Thoughts?<br>
>><br>
>><br>
>> --<br>
>> Thanks,<br>
>> Andrew Svetlov<br>
>> _______________________________________________<br>
>> Python-ideas mailing list<br>
>> <a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
>> <a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
>> Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/codeofconduct/</a><br>
><br>
><br>
><br>
><br>
> --<br>
> --Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)<br>
<br>
<br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
Thanks,<br>
Andrew Svetlov<br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)
</div>