[Python-ideas] PEP 3156 feedback: wait_one vs par vs concurrent.futures.wait

Guido van Rossum guido at python.org
Sat Dec 22 16:54:55 CET 2012


On Sat, Dec 22, 2012 at 12:04 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Sat, Dec 22, 2012 at 4:20 PM, Guido van Rossum <guido at python.org> wrote:
>> I did update the PEP. There are some questions about details; e.g. I
>> think the 'fs' argument should allow a mixture of Futures and
>> coroutines (the latter will be wrapped Tasks) and the sets returned by
>> wait() should contain Futures and Tasks.
>
> Yes, I think I wrote my examples that way, even though I didn't say
> that in the text.

Good.

>> You propose that
>> as_completed() returns an iterator whose items are coroutines; why not
>> Futures? (They're more versatile even if slightly slower that
>> coroutines.) I can sort of see the reasoning but want to tease out
>> whether you meant it that way.
>
> I deliberately chose to return coroutines. My rationale is to be able
> to handle the case where multiple operations become ready without
> having to make multiple trips around the event loop by having the
> iterator switch between two modes: when the complete set is empty, it
> yields a coroutine that calls wait and then returns the first complete
> future, while when there are already complete futures available, it
> yields a coroutine that just returns one of them immediately. It's
> really the same rationale as that for having @coroutine not
> automatically wrap things in Task - if we can avoid the event loop in
> cases that don't actually need to wait for an event, that's a good
> thing.

I think I see it now. The first item yielded is the simplest thing
that can be used with yield-from, i.e. a coroutine. Then if multiple
futures are ready at once, you return an item of the same type, i.e. a
coroutine. This is essentially wrapping a Future in a coroutine! If we
could live with the items being alternatingly coroutines and Futures,
we could just return the Future in this case. BTW, yield from <future>
need not go to the scheduler if the Future is already done -- the
Future,__iter__ method should be:

    def __iter__(self):
        if not self.done():
            yield self  # This tells Task to wait for completion.
        return self.result()  # May raise too.

(I forgot this previously.)

>> Also, we can't have __next__() raise
>> TimeoutError, since it never blocks; it will have to be the coroutine
>> (or Future) returned by __next__().
>
> Yeah, any exceptions should happen at the yield from call inside the
> loop. I *think* my implementation achieves that (since the coroutine
> instances it creates are passed out to the for loop for further
> processing), but it's quite possible I missed something.

It'll come out in implementation (in two weeks, maybe).

-- 
--Guido van Rossum (python.org/~guido)



More information about the Python-ideas mailing list