[Python-ideas] PEP 525: Asynchronous Generators
Yury Selivanov
yselivanov.ml at gmail.com
Thu Aug 4 11:17:55 EDT 2016
Hi Sven,
On 2016-08-04 9:20 AM, Sven R. Kunze wrote:
> Hey Yury,
>
> that's a great proposal!
>
>
> On 03.08.2016 00:31, Yury Selivanov wrote:
>>
>> class Ticker:
>> """Yield numbers from 0 to `to` every `delay` seconds."""
>>
>> def __init__(self, delay, to):
>> self.delay = delay
>> self.i = 0
>> self.to = to
>>
>> def __aiter__(self):
>> return self
>>
>> async def __anext__(self):
>> i = self.i
>> if i >= self.to:
>> raise StopAsyncIteration
>> self.i += 1
>> if i:
>> await asyncio.sleep(self.delay)
>> return i
>>
>>
>> The same can be implemented as a much simpler asynchronous generator::
>>
>> async def ticker(delay, to):
>> """Yield numbers from 0 to `to` every `delay` seconds."""
>> for i in range(to):
>> yield i
>> await asyncio.sleep(delay)
>>
>
> That's a great motivational example. +1
>
> Especially when reading the venerable PEP 255 (Q/A part), this also
> gets rid of the "low-level detail": "raise StopAsyncIteration". This
> could also be worth mentioning in the motivation part for PEP 525.
Thanks!
[..]
> From your answer to Stefan, I get the impression that the reason why
> we actual need all those a* methods (basically a duplication of the
> existing gen protocol), is the fact that normal generators can be
> converted to coroutines. That means, 'yield' still can be used in both
> ways.
>
> So, it's a technical symptom of the backwards-compatibility rather
> than something that cannot be avoided by design. Is this correct?
>
async/await in Python is implemented on top of the generator protocol.
Any 'await' is either awaiting on a coroutine or on a Future-like
object. Future-like objects are defined by implementing the __await__
method, which should return a generator.
So coroutines and generators are very intimately tied to each other, and
that's *by design*.
Any coroutine that iterates over an asynchronous generator uses the
generator protocol behind the scenes. So we have to multiplex the async
generaotor's "yields" into the generator protocol in such a way, that it
stays isolated, and does not interfere with the "yields" that drive
async/await.
>
>
> If it's correct, would you think it would make sense to get rid of the
> a* in a later iteration of the async capabilities of Python? So, just
> using the normal generator protocol again?
Because async generators will contain 'await' expressions, we have to
have a* methods (although we can name them without the "a" prefix, but I
believe that would be confusing for many users).
>
>
> One note on all examples but the last. Reading those examples, it
> creates the illusion of actual working code which is not the case,
> right? One would always need to 1) wrap module-level statements into
> its own coroutine, 2) create an event-loop and 3) run it. Do you think
> clarifying this in the PEP makes sense?
I'll think about this, thanks! Maybe I can add a line in the beginning
of the "Specification" section.
>
>
> Thanks again for your hard work here. Async generators definitely
> completes the picture.
Thank you, Sven
Yury
More information about the Python-ideas
mailing list