This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author André Caron
Recipients André Caron, asvetlov, brett.cannon, gvanrossum, martin.panter, ncoghlan, vstinner, yselivanov
Date 2016-02-13.20:21:23
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1455394884.24.0.135751285394.issue25887@psf.upfronthosting.co.za>
In-reply-to
Content
> 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().
History
Date User Action Args
2016-02-13 20:21:24André Caronsetrecipients: + André Caron, gvanrossum, brett.cannon, ncoghlan, vstinner, asvetlov, martin.panter, yselivanov
2016-02-13 20:21:24André Caronsetmessageid: <1455394884.24.0.135751285394.issue25887@psf.upfronthosting.co.za>
2016-02-13 20:21:24André Caronlinkissue25887 messages
2016-02-13 20:21:23André Caroncreate