[Async-sig] PEP: asynchronous generators

Yury Selivanov yselivanov at gmail.com
Fri Jul 29 14:07:45 EDT 2016


Few comments below:

> On Jul 29, 2016, at 1:57 PM, Brett Cannon <brett at python.org> wrote:
> 
> 
> 
> On Fri, 29 Jul 2016 at 10:46 Yury Selivanov <yselivanov at gmail.com> wrote:
> Thanks a lot for the feedback, Brett!  Comments inlined below:
> 
> > On Jul 29, 2016, at 1:25 PM, Brett Cannon <brett at python.org> wrote:
> >
> [..]
> >
> > Performance is an additional point for this proposal: in our testing of
> > the reference implementation, asynchronous generators are *2x* faster
> > than an equivalent implemented as an asynchronous iterator.
> >
> > Another motivation is that types.coroutine becomes purely a backwards-compatibility/low-level thing that is no longer required for event loop frameworks to use on their generators which provide their async API. So now an async framework can be written entirely in terms of def and async def and not def and @types.coroutine.
> 
> A slight misunderstanding here: @types.coroutine turns a normal old-style generator into an awaitable object.  That isn’t directly related to asynchronous iteration.  Frameworks like curio will continue using @types.coroutine to implement future-like objects in event loops.
> 
> Ah, OK. So that would be yet another PEP to make that kind of change (and another keyword).

TBH I’m not really sure we need that.  To separate coroutines from generators completely, you don’t just need another keyword — you basically need to have a separate parallel implementation of the whole iteration protocol.  I think @types.coroutine is a nice glue between two worlds, allowing us to reuse the code efficiently.  Again, just my 2 cents.

> >
> > I'm going to ask this now instead of later when there's more motivation behind this question: do we need to append "a" to every async method we have? If asynchronous generators won't have a normal close() then why can't it just be close(), especially if people are not going to be calling it directly and instead it will be  event loops? I'm just leery of codifying this practice of prepending "a" to every async method or function and ending up in a future where I get tired of a specific letter of the alphabet.
> 
> I decided to use the prefix because we already use it in magic method names: __anext__ and __aiter__.  I think it also makes it easier to understand the API of async generators (and understand how it’s different from sync generators API).
> 
> And while it’s entirely possible to drop the ‘a’ for async generator API, it’s not so simple for other cases.  Later, for Python 3.7, we might consider adding ‘aiter()’ and ‘anext()’ builtins, for which we’d have to use ‘a’ or ‘async’ prefix (we can’t reuse 'iter()' and 'next()’ for async generators).
> 
> I guess we just need to decide as a group that an 'a' prefix is what we want to signify something is asynchronous vs some other prefix like 'a_' or 'async', or 'async_' as people will follow this style choice in their own code going forward.

I’m open to having this discussion.  I don’t have a strong preference here; I, personally, like the ‘a’ prefix slightly better, because it’s consistent with __a*__ methods and easy to type.

[..]
> We actually added that in 3.5 (last minute!).
> 
> For sync generators the field is called ‘.gi_yieldfrom’, for coroutines it’s ‘.cr_await’, and for proposed async generators it will be ‘.ag_await’.
> 
> I would also clarify that "waiting on" means "what `await` has been called on (if anything as an `await` call might not have been used)" and not what the last yielded object happened to be (which is what my brain initially thought it was simply because the async generator is paused on the event loop returning based on what was yielded).

OK, I’ll try to clarify this!

Yury


More information about the Async-sig mailing list