[Python-Dev] PEP 492: async/await in Python; v3
Yury Selivanov
yselivanov.ml at gmail.com
Wed Apr 29 16:16:45 CEST 2015
Greg,
On 2015-04-29 5:12 AM, Greg Ewing wrote:
> Yury Selivanov wrote:
>
>> It's important to at least have 'iscoroutine' -- to check that
>> the object is a coroutine function. A typical use-case would be
>> a web framework that lets you to bind coroutines to specific
>> http methods/paths:
>>
>> @http.get('/spam')
>> async def handle_spam(request):
>> ...
> >
>> The other thing is that it's easy to implement this function
>> for CPython: just check for CO_COROUTINE flag.
>
> But isn't that too restrictive? Any function that returns
> an awaitable object would work in the above case.
It's just an example. All in all, I think that we should have
full coverage of python objects in the inspect module. There are
many possible use cases besides the one that I used -- runtime
introspection, reflection, debugging etc, where you might need
them.
>
>>>> One of the most frequent mistakes that people make when using
>>>> generators as coroutines is forgetting to use ``yield from``::
>>
>> I think it's a mistake that a lot of beginners may make at some
>> point (and in this sense it's frequent). I really doubt that
>> once you were hit by it more than two times you would make it
>> again.
>
> What about when you change an existing non-suspendable
> function to make it suspendable, and have to deal with
> the ripple-on effects of that? Seems to me that affects
> everyone, not just beginners.
I've been using coroutines on a daily basis for 6 or 7 years now,
long before asyncio we had a coroutine-based framework at my firm
(yield + trampoline). Neither I nor my colleagues had any
problems with refactoring the code. I really try to speak from
my experience when I say that it's not that big of a problem.
Anyways, the PEP provides set_coroutine_wrapper which should solve
the problem.
>
>>>> 3. ``yield from`` does not accept coroutine objects from plain Python
>>>> generators (*not* generator-based coroutines.)
>>>>
>>> What exactly are "coroutine objects
>>> from plain Python generators"?)
>>
>> # *Not* decorated with @coroutine
>> def some_algorithm_impl():
>> yield 1
>> yield from native_coroutine() # <- this is a bug
>
> So what you really mean is "yield-from, when used inside
> a function that doesn't have @coroutine applied to it,
> will not accept a coroutine object", is that right? If
> so, I think this part needs re-wording, because it sounded
> like you meant something quite different.
>
> I'm not sure I like this -- it seems weird that applying
> a decorator to a function should affect the semantics
> of something *inside* the function -- especially a piece
> of built-in syntax such as 'yield from'. It's similar
> to the idea of replacing 'async def' with a decorator,
> which you say you're against.
This is for the transition period. We don't want to break
existing asyncio code. But we do want coroutines to be
a separate concept from generators. It doesn't make any
sense to iterate through coroutines or to yield-from them.
We can deprecate @coroutine decorator in 3.6 or 3.7 and
at some time remove it.
>
> BTW, by "coroutine object", do you mean only objects
> returned by an async def function, or any object having
> an __await__ method? I think a lot of things would be
> clearer if we could replace the term "coroutine object"
> with "awaitable object" everywhere.
The PEP clearly separates awaitbale from coroutine objects.
- coroutine object is returned from coroutine call.
- awaitable is either a coroutine object or an object with
__await__.
list(), tuple(), iter(), next(), for..in etc. won't work
on objects with __await__ (unless they implement __iter__).
The problem I was discussing is about specifically
'yield from' and 'coroutine object'.
>
>> ``yield from`` does not accept *native coroutine objects*
>> from regular Python generators
>
> It's the "from" there that's confusing -- it sounds
> like you're talking about where the argument to
> yield-from comes from, rather than where the yield-from
> expression resides. In other words, we though you were
> proposing to disallow *this*:
>
> # *Not* decorated with @coroutine
> def some_algorithm_impl():
> yield 1
> yield from iterator_implemented_by_generator()
>
> I hope to agree that this is a perfectly legitimate
> thing to do, and should remain so?
>
Sure it's perfectly normal ;) I apologize for the poor
wording.
Yury
More information about the Python-Dev
mailing list