This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Ben.Darnell
Recipients Ben.Darnell, Yury.Selivanov, asvetlov, gvanrossum, ncoghlan, scoder, vstinner, yselivanov
Date 2015-06-10.03:11:08
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <CAFkYKJ5BNd6-BEg8vt8wi9n-AoJJnoTTGhJNsakt04=0rxKR5w@mail.gmail.com>
In-reply-to <1433902330.22.0.173275925288.issue24400@psf.upfronthosting.co.za>
Content
On Tue, Jun 9, 2015 at 10:12 PM, Yury Selivanov <report@bugs.python.org>
wrote:

>
> Yury Selivanov added the comment:
>
> > All this checking for coroutine-ness feels very strange to me. It's
> anti-duck-typing: [..]
>
> Why is it "anti-duck-typing"?  Awaitable is an object that implements
> __await__.  With this patch coroutines are a separate type with __await__
> (although, ceval doesn't use it to make things faster).
>

Anti-duck-typing isn't quite the right word. What I meant was that Python
3.4 had generators that were used as coroutines. When we introduced
__await__ in 3.5, we could have added __await__ as a method for all
generators, since all generators have the necessary send/throw/close
methods. But we didn't, and now we require an explicit marker that a given
object was intended for a particular use instead of inferring that
intention from the set of methods available.

>
> In asyncio we check for "coroutine-ness" only to raise errors if someone
> passes a wrong object, or to make @asyncio.coroutine work (which will go
> away eventually).
>

The check for coroutine-ness is not just in asyncio; it happens in the core
interpreter. Tornado has to adapt to this check in order to interoperate
with 'async def' coroutines.

>
> > Now, not only must it return a generator with the special coroutine
> flag, the callable itself must be of the right type [..]
>
> Not sure what you mean here.  It doesn't matter what callable is.  It only
> matters if it returns a native coroutine, a generator-based coroutine, or
> an object with "__await__".
>

The type of the callable matters for the types.coroutine decorator. In
order to get a coroutine object instead of a generator object, I must apply
types.coroutine to the actual underlying generator, and not any wrapper.

>
> > Attempting to divide generators into awaitable and non-awaitable subsets
> is a complex solution to a problem that I'm not convinced is real.
>
> Well, 'await' expression is a new operator, and it makes total sense to
> limit its usage only to awaitables.  Awaiting on a generator that yields a
> fibonacci sequence just doesn't make any sense, and *is* error prone.  I
> think it would be a major mistake to allow this just to make things a
> little bit more convenient during the transition period.
>
> This particular patch does not divide generators in awaitables and
> non-awaitables, it introduces a new type for 'async def' coroutines.  All
> confusion with old generator-based coroutines and @coroutine decorator is
> here only because we try to be backwards compatible; the compatibility
> layer can be removed in 3.7 or 3.8.
>

There are three eras of coroutines to consider: 'async def' in 3.5+, 'yield
from' in 3.3-3.4, and 'yield' in 2.5+. I'm trying to provide a path from
'yield' to 'async def'; this compatibility layer will remain relevant as
long as people are migrating from 2.7.

>
> > Was there a problem in practice with Python 3.4's asyncio in which
> people used "yield from" in a coroutine with generators that were intended
> to be iterators instead?
>
> Yes, a lot of people were confused where they have coroutines and where
> they have generators, and this was even mentioned in the Rationale section
> of the PEP.
>

I understand that yield-based coroutines can be confusing, but is this
particular kind of confusion bad enough that if someone writes 'await
fibonacci_generator()' we have to raise "TypeError: object generator can't
be used in 'await' expression" instead of "RuntimeError: Task got bad
yield: 1"? (that error message from asyncio could definitely be improved,
but the fact that no one has improved it suggests that the problem isn't
that severe)

My goal here is to make it possible for Tornado applications running on 3.5
to use 'async def' and 'await' even though Tornado itself must remain
compatible with 2.7 (as do many of the libraries that make up the Tornado
ecosystem; I don't want libraries to have to update for compatibility with
this feature). This is doable (I think) but non-trivial in the current
design; making all generators awaitable would make it easier.
History
Date User Action Args
2015-06-10 03:11:09Ben.Darnellsetrecipients: + Ben.Darnell, gvanrossum, ncoghlan, scoder, vstinner, asvetlov, Yury.Selivanov, yselivanov
2015-06-10 03:11:09Ben.Darnelllinkissue24400 messages
2015-06-10 03:11:08Ben.Darnellcreate