New submission from André Caron:

When the asyncio.wait() function with coroutine objects as inputs, it is 
impossbible to extract the results reliably.

This issue arises because asyncio.wait() returns an unordered set of futures 
against which membership tests of coroutine objects always fail.

The issue is made even worse by the fact that coroutine objects cannot be 
awaited multiple times (see https://bugs.python.org/issue25887).  Any await 
expression on the coroutine object after the call to asyncio.wait() returns 
None, regardless of the coroutine's return value.

  (See attached `asyncio-wait-coroutine.py` for an example of both these 
issues.)

In the worst case, multiple inputs are coroutine objects and the set of 
returned futures contains return values but there is no way to determine which 
result corresponds to which coroutine call.

To work around this issue, callers need to explicitly use 
asyncio.ensure_future() on coroutine objects before calling asyncio.wait().

  (See comment in `asyncio-wait-coroutine.py` for an example "fix").

Note that, in general, it is not possible to know ahead of time whether all 
inputs to asyncio.wait() are coroutines or futures.  Furthermore, the fact that 
a given third-party library function is implemented as a regular function that 
returns a Future or a proper coroutine is an implementation decision which may 
not be part of the public interface.  Even if it is, the inputs to 
asyncio.wait() may come from complex code paths and it may be difficult to 
verify that all of them end up producing a Future.

As a consequence, the only reliable way to recover all results from 
asyncio.wait() is to explicitly call asyncio.ensure_future() on each of the 
inputs.

When doing so, both the membership test against the `done` set and the await 
expressions work as expected.

Quickly, there are several possible solutions:
- allow programs to await coroutine multiple times;
- make the set membership test of a coroutine object succeed; or
- change support for coroutine objects as inputs to asyncio.wait():
** update documentation for asyncio.wait() to explain this limitation; or
** explicitly reject coroutine objects; or
** warn when passing coroutine objects as inputs -- unless wrapped.

Related issue: https://bugs.python.org/issue25887 proposes a patch to change 
the behaviour of awaiting a coroutine object multiple times in order to produce 
a RuntimeError on all awaits after the 1st.  While that change in behaviour 
would make it easier to diagnose the loss of the return value, it does not fix 
this issue.

----------
components: asyncio
files: asyncio-wait-coroutine.py
messages: 260250
nosy: André Caron, gvanrossum, haypo, yselivanov
priority: normal
severity: normal
status: open
title: asyncio.wait loses coroutine return value
versions: Python 3.5
Added file: http://bugs.python.org/file41914/asyncio-wait-coroutine.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue26357>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to