[Python-ideas] async/await in Python

Chris Angelico rosuav at gmail.com
Sat Apr 18 00:46:27 CEST 2015


On Sat, Apr 18, 2015 at 8:18 AM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> On 2015-04-17 6:00 PM, Chris Angelico wrote:
>>
>> On Sat, Apr 18, 2015 at 4:58 AM, Yury Selivanov <yselivanov.ml at gmail.com>
>> wrote:
>>>      running = True
>>>      while running:
>>>          try:
>>>              TARGET = await type(iter).__anext__(iter)
>>>          except StopAsyncIteration:
>>>              running = False
>>>          else:
>>>              BLOCK
>>>      else:
>>>          BLOCK2
>>
>> (Not sure why you don't just use "break" instead of "running = False"?
>> Maybe I'm blind to some distinction here.)
>
> Because if you use break, the "else: BLOCK2" won't execute, but
> it should, as StopAsyncIteration is not a regular exception, but
> something to signal that the iteration is over.

Ah, gotcha. Carry on!

>> Can't a coroutine simply use 'return'? I'm not hugely familiar with
>> them, but I'm not understanding here why you need a completely
>> separate exception - and, more importantly, why you wouldn't have the
>> same consideration of "StopAsyncIteration leakage". It ought to be
>> possible for the coroutine to return, StopIteration be synthesized,
>> and the __anext__ function to bubble that out - exactly the way it
>> does for generators today.
>
>
> Unfortunately, there is no way we can enable StopIteration to do
> the same thing that StopAsyncIteration does.
>
> 'return' in coroutines is implemented with 'StopIteration' exception
> internally, so there is no way (without ugly hacks) to distinguish
> before plain returns and desire to stop the iteration.

All you need to do is have the same StopIteration -> RuntimeError
handling that PEP 479 proposes, and then you can confidently accept a
StopIteration coming out of __anext__ as a signal that the coroutine
returned. It might require a small hack during the transitional time
(eg "all functions defined with 'async def' behave as if defined in
the presence of a 'from __future__ import generator_stop' directive"),
but once PEP 479 handling becomes standard, generators and coroutines
will all always follow this distinction. Generators either yield or
return, coroutines either await or return, __[a]next__ methods either
return or raise StopIteration, and any other issues become exceptions
that bubble up.

Since you're already utilizing a lot of generator-like behaviour, it
shouldn't be a problem to handle exceptions the same way. The logic
around a generator's __next__ method is broadly thus:

* Resume the function's execution
* If it returned: Synthesize a StopIteration.
* Else if it raised StopIteration: Raise RuntimeError.
* Else if it raised anything else: Let it bubble up.
* Else it yielded something, so return it.

There's no conflict here, because they're checked in strict order. It
ought to be possible to do the same thing. The only reason for messy
hacks is to support Python 2.x, where "return X" (for any X other than
None) doesn't work; given that you're adding new syntax here, the
concern shouldn't apply.

> Let's see what python-ideas thinks about it.  I'm fine if everybody
> wants __future__ imports.  I will only have to rollback my changes
> in tokenizer.c and change few tokens in Grammar to make the
> reference implementation work.

In case it wasn't clear from my previous post, I'm +1 on using a
__future__ import. Victor's idea of an optional directive seems
interesting, but I'm not sure how useful it'd be in reality; does
complicating the rules offer more benefit than simply having a keyword
governed by __future__?

>>> Comprehensions
>>> --------------
>>>
>>> For the sake of restricting the broadness of this PEP there is no new
>>> syntax
>>> for asynchronous comprehensions.  This should be considered in a separate
>>> PEP,
>>> if there is a strong demand for this feature.
>>
>> Likewise asynchronous lambda functions (or maybe I just missed it).
>
> Right. Right now I'm just not sure they would be useful at all,
> whereas I can imagine some usecases for comprehensions ;)

Sure. I'm making no statement as to whether or not async lambda is
worth implementing, but just that it's another subproposal that isn't
being dealt with in this PEP.

ChrisA


More information about the Python-ideas mailing list