[Python-Dev] async/await behavior on multiple calls
Kevin Conway
kevinjacobconway at gmail.com
Wed Dec 16 00:55:04 EST 2015
I agree with Barry. We need more material that introduces the community to
the new async/await syntax and the new concepts they bring. We borrowed the
words from other languages but not all of their behaviours.
With coroutines in particular, we can do a better job of describing the
differences between them and the previous generator-coroutines, the rules
regarding what - if anything - is emitted from a '.send(<value>)', and how
await resolves to a value. If you read through the asyncio Task code enough
you'll figure it out, but we can't expect the community as a whole to learn
the language, or asyncio, that way.
Back to the OP's issue. The behaviour you are seeing of None being the
value of an exhausted coroutine is consistent with that of an exhausted
generator. Pushing the iterator with __next__() or .send() after completion
results in a StopIteration being raised with a value of None regardless of
what the final yielded/returned value was. Futures can be awaited multiple
times because the __iter__/__await__ method defined causes them to raise
StopIteration with the resolved value.
I think the list is trying to tell you that awaiting a coro multiple times
is simply not a valid case in Python because they are exhaustible
resources. In asyncio, they are primarily a helpful mechanism for shipping
promises to the Task wrapper. In virtually all cases the pattern is:
> await some_async_def()
and almost never:
> coro = some_async_def()
> await coro
On Tue, Dec 15, 2015 at 9:34 PM Yury Selivanov <yselivanov.ml at gmail.com>
wrote:
> Roy,
>
> On 2015-12-15 8:29 PM, Roy Williams wrote:
> [..]
> >
> > My proposal would be to automatically wrap the return value from an
> > `async` function or any object implementing `__await__` in a future
> > with `asyncio.ensure_future()`. This would allow async/await code to
> > behave in a similar manner to other languages implementing async/await
> > and would remain compatible with existing code using asyncio.
> >
> > What's your thoughts?
>
> Other languages, such as JavaScript, have a notion of event loop
> integrated on a very deep level. In Python, there is no centralized
> event loop, and asyncio is just one way of implementing one.
>
> In asyncio, Future objects are designed to inter-operate with an event
> loop (that's also true for JS Promises), which means that in order to
> automatically wrap Python coroutines in Futures, we'd have to define the
> event loop deep in Python core. Otherwise it's impossible to implement
> 'Future.add_done_callback', since there would be nothing that calls the
> callbacks on completion.
>
> To avoid adding a built-in event loop, PEP 492 introduced coroutines as
> an abstract language concept. David Beazley, for instance, doesn't like
> Futures, and his new framework 'curio' does not have them at all.
>
> I highly doubt that we want to add a generalized event loop in Python
> core, define a generalized Future interface, and make coroutines return
> it. It's simply too much work with no clear wins.
>
> Now, your initial email highlights another problem:
>
> coro = coroutine()
> print(await coro) # will print the result of coroutine
> await coro # prints None
>
> This is a bug that needs to be fixed. We have two options:
>
> 1. Cache the result when the coroutine object is awaited first time.
> Return the cached result when the coroutine object is awaited again.
>
> 2. Raise an error if the coroutine object is awaited more than once.
>
> The (1) option would solve your problem. But it also introduces new
> complexity: the GC of result will be delayed; more importantly, some
> users will wonder if we cache the result or run the coroutine again.
> It's just not obvious.
>
> The (2) option is Pythonic and simple to understand/debug, IMHO. In
> this case, the best way for you to solve your initial problem, would be
> to have a decorator around your tasks. The decorator should wrap
> coroutines with Futures (with asyncio.ensure_future) and everything will
> work as you expect.
>
> Thanks,
> Yury
>
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/kevinjacobconway%40gmail.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20151216/ee1be088/attachment.html>
More information about the Python-Dev
mailing list