[Python-Dev] [PEP 3148] futures - execute computations asynchronously

P.J. Eby pje at telecommunity.com
Sun Mar 7 18:57:31 CET 2010


At 08:39 AM 3/7/2010 -0800, Jeffrey Yasskin wrote:
>On Sun, Mar 7, 2010 at 7:48 AM, P.J. Eby <pje at telecommunity.com> wrote:
> > At 02:49 PM 3/7/2010 +1000, Nick Coghlan wrote:
> >>
> >> P.J. Eby wrote:
> >> > (Personally, I think it would be better to just drop the ambitious title
> >> > and scope, and go for the "nice task queue" scope. Â I 
> imagine, too, that
> >> > in that case Jean-Paul wouldn't need to worry about it being raised as a
> >> > future objection to Deferreds or some such getting into the stdlib.)
> >>
> >> This may be a terminology thing - to me futures *are* just a nice way to
> >> handle farming tasks out to worker threads or processes. You seem to see
> >> them as something more comprehensive than that.
> >
> > Actual futures are, yes. Â Specifically, futures are a mechanism for
> > asynchronous computation, whereas the PEP seems to be all about
> > synchronously managing parallel tasks. Â That's a huge difference.
> >
> > Technically, the things in the PEP (and by extension, Java's futures) match
> > the letter of the definition of a future, but not (IMO) the 
> spirit. Â There's
> > no clean way to compose them, and at base they're more about parallelism
> > than asynchrony.
>
>Do you have an example of a language or library that uses the term
>"future" to refer to what you're talking about? I'm curious to see
>what it looks like.

The wikipedia page menetioned earlier in the discussion has several 
examples.  Twisted's Deferreds are probably the best example of such 
a system in Python, though, as far as I know.  The features proposed 
in the PEP are basically akin to Twisted's deferToThread(), i.e. 
"return a future for running this code in some other thread".

However, you could easily make your own thread or process pool for 
executing tasks, using Deferreds as your "future" objects; 
deferToThread() is not particularly special, it's just one possible 
"executor", to use the PEP's terminology.  Likewise, deferreds are 
not limited to representing parallel task execution - they can also 
represent asynchronous events such as incoming I/O or a waited-for mouse click.

Deferreds allow composing calculation by stacking callbacks (in 
continuation-passing style), but they're most Pythonic (IMO) when 
used with a coroutine wrapping system like Eventlet or my earlier 
peak.events framework, so that you can use them in "yield" 
expressions.  That way you can write synchronous-looking code that 
nonetheless executes asynchronously.

Twisted uses Deferreds extensively, both for I/O and IPC, and of 
course for database access.  However, the 'defer' module itself is 
conceptually distinct from both the I/O system, event loop, and 
threads: it's a largely-generic framework for managing asynchronous 
computation.  Parallel task queueing is simply *one* possible 
application of Deferreds; their actual purpose is to provide a common 
API for working with values that aren't yet known.

That is to say, futures.

In contrast, the PEP manages only a very limited sort of "future" - 
the completion of a single task, which must be synchronously waited 
for.  If one "future" in the PEP needs to wait for another, you tie 
up that thread or process in a busy loop...  which rather limits how 
much parallelism you can have.

Deferreds also allow you to write code that doesn't *care* whether 
the value has been determined or not...  you can simply stack on what 
code you want to have run when the value is available, and it runs 
immediately if the value is there.

Likewise, a deferred is not tied to the execution of a single piece 
of code - it's more of a rendezvous or synchronization point, that 
can be given a value to "fire" with.  (In contrast, the PEP's 
"futures" are tightly coupled to a task execution model: they have a 
notion of running and being cancelled, for example.)

For these reasons, I'd say that Deferreds are much more deserving of 
the title "futures", especially since there is no need to call a 
simple task queue a "futures" system.  (Unless you're Java, I 
suppose, in which case you might want the name for marketing 
reasons.  ;-) But in Python I assume we'd like to call a spade a 
spade, and a task queue a task queue.)



More information about the Python-Dev mailing list