[Python-Dev] async/await behavior on multiple calls

Roy Williams rwilliams at lyft.com
Wed Dec 16 04:50:20 EST 2015


I totally agree that async/await should not be tied to any underlying
message pump/event loop.  Ensuring that async/await works with existing
systems like Tornado is great.

As for the two options, option 1 is the expected behavior from developers
coming from other languages implementing async/await which is why I found
the existing behavior to be so unintuitive.  To Barry and Kevin's point,
this problem is exacerbated by a lack of documentation and examples that
one can follow to learn about the Pythonic approach to async/await.

Thanks,
Roy

On Tue, Dec 15, 2015 at 7:33 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/rwilliams%40lyft.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20151216/0e253d95/attachment-0001.html>


More information about the Python-Dev mailing list