André Caron added the comment:

> I believe you're not using the asyncio.task() function correctly.

I assume you meant asyncio.wait().

I just updated my gist with a variant of my example that uses the (done, 
pending) pair returned by asyncio.wait() as you suggested.

The set of done futures that is returned does not help in this case because you 
need to test objects by set membership using something like "if f1 in done:", 
which will never be true because f1 is a coroutine object and the set contains 
a wrapper returned by asyncio.ensure_future().

So we're back to square 1.  Because you cannot await multiple times on a 
coroutine object (in contrast to futures), you will need to explicitly call 
asyncio.ensure_future() on everything you pass to asyncio.wait() if you care 
about the future's result -- which is more often than not in my experience.

> There are many reasons as to why we don't want coroutines to be awaitable
many times.  One of them is that we don't want low-level coroutine
objects to hold references to return values.  Coroutines in Python
are exhaustible resources (like generators).

I understand concerns for efficiency and management of scarce resources.

However, I don't understand your comment.  Maybe this has something to do with 
CPython/asyncio internals, which I know nothing about.  If my code keeps a 
reference to the coroutine object, it can't be released right?  I don't see how 
adding a reference to the return value or wrapping the coroutine object in a 
Task wrapper (in order to recover the return value) will affect the allocation 
of coroutine resources.

> Well, coroutines are much more lower level than Future/Tasks.

>From an implementer's point of view, maybe.  From a user's point of vue, the 
>value of having an "awaitable" concept is that I can use different objects in 
>the same way.  If the semantics of await expressions vary depending on the 
>awaitable's type, then the value of the abstraction is reduced.

If we go back to the core of the issue, the real problem here is the fact that 
the current behaviour of multiple awaits on a coroutine object is surprising: 
nobody expects it to return None the 2nd time around.

Raising a RuntimeError instead of returning None is still surprising behaviour 
IMO.

In addition to that, the error message that was agreed upon in this issue 
suggests a programming error (you're not _supposed_ to await twice), but what 
I'm getting to here with my example is that asyncio.wait() is a 
common/legitimate use case of this.

Anyways, if you insist on considering this a programming error, you should 
probably reject coroutine objects in calls to asyncio.wait() since there will 
be effectively no way of recovering the return value after the call to 
asyncio.wait().

----------

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

Reply via email to