Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #63389

Trying to wrap my head around futures and coroutines

Path csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.xs4all.nl!newsfeed1.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail
Return-Path <skip.montanaro@gmail.com>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.130
X-Spam-Level *
X-Spam-Evidence '*H*': 0.74; '*S*': 0.00; 'algorithm': 0.04; 'buttons': 0.09; 'def': 0.12; 'gui': 0.12; 'canceled': 0.16; 'corresponds': 0.16; 'hypothetical': 0.16; 'opposite': 0.16; 'perceived': 0.16; 's/he': 0.16; 'simple.': 0.16; 'code.': 0.18; 'bit': 0.19; 'basically': 0.19; 'seems': 0.21; '(the': 0.22; 'programming': 0.22; 'comfortable': 0.22; 'instead.': 0.24; 'skip': 0.24; 'decide': 0.24; 'fine': 0.24; 'looks': 0.24; 'sort': 0.25; "i've": 0.25; 'task': 0.26; 'this:': 0.26; 'header:In-Reply- To:1': 0.27; 'possibility': 0.29; 'thus': 0.29; '???': 0.30; 'reaches': 0.30; 'message-id:@mail.gmail.com': 0.30; "i'm": 0.30; 'work.': 0.31; 'code': 0.31; 'that.': 0.31; '"do': 0.31; 'breaking': 0.31; 'complete,': 0.31; 'probably': 0.32; 'stuff': 0.32; 'option': 0.32; 'run': 0.32; 'running': 0.33; 'trouble': 0.34; "i'd": 0.34; 'something': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'cancel': 0.36; 'executing': 0.36; 'reality': 0.36; 'vice': 0.36; 'yield': 0.36; 'doing': 0.36; 'similar': 0.36; 'should': 0.36; 'so,': 0.37; 'two': 0.37; 'being': 0.38; 'gmail': 0.38; 'tasks': 0.38; 'to:addr :python-list': 0.38; 'little': 0.38; 'skip:& 20': 0.39; 'structure': 0.39; 'sure': 0.39; 'to:addr:python.org': 0.39; 'enough': 0.39; 'how': 0.40; 'future': 0.60; 'catch': 0.60; 'signal': 0.60; 'simple,': 0.60; 'new': 0.61; 'world.': 0.61; 'simple': 0.61; 'first': 0.61; 'complete': 0.62; 'real': 0.63; 'world': 0.66; 'roles': 0.68; 'started.': 0.68; 'statement,': 0.68; 'facilities': 0.69; 'user,': 0.69; 'safe': 0.72; 'obvious': 0.74; 'guaranteed': 0.75; '100%': 0.77; '&quot;do': 0.84; 'calculations': 0.84; 'guts': 0.84; 'activity,': 0.91; 'execution,': 0.91; 'notion': 0.91
DKIM-Signature v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=ibV1csAb0gLt1gC5Xhyhz8blFWKeAmJ4EpSwkPge+zA=; b=jAL5uXoEK6kL1+Pr4HMP8Ioppes37piV/drMcrH36R+F2JU65TUoksPOVxxjkJjvFc 6HcXKCkCdUklsA5F4lIzD4Whj2jvrh0ufwdfJKead0e4NS6LtKUWnjbrpRmD61cMKzI+ 6a2gz+Q1ANExz4qb2o8fgANDHLO8oNL5yPCOv6wgd8CJsXNtOPxtw56V/8EIfB8pEqmA xjH/qSeuzfLMgUs9a4QSa5bKVwuUsaUA5vwJqgNhP0GCFxnH6kIAbpUDzvlm4kCX/PLb yYeR6khwmhaWBHePJoNpIYZSf5gaBdIwxN0h/bzOjJYTtFWmLCr/fqoMbJLnAP55c9Nf f72g==
MIME-Version 1.0
X-Received by 10.50.43.134 with SMTP id w6mr22874700igl.20.1389056160342; Mon, 06 Jan 2014 16:56:00 -0800 (PST)
In-Reply-To <CANc-5UzZj9vNdZVvDNosaGaOLXhOykagF_HkqafYjnoNguD2Mw@mail.gmail.com>
References <CANc-5UzZj9vNdZVvDNosaGaOLXhOykagF_HkqafYjnoNguD2Mw@mail.gmail.com>
Date Mon, 6 Jan 2014 18:56:00 -0600
Subject Trying to wrap my head around futures and coroutines
From Skip Montanaro <skip.montanaro@gmail.com>
To Python <python-list@python.org>
Content-Type multipart/alternative; boundary=089e01184b0c03546104ef56d7f3
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.15
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.5101.1389056164.18130.python-list@python.org> (permalink)
Lines 149
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1389056165 news.xs4all.nl 2838 [2001:888:2000:d::a6]:59194
X-Complaints-To abuse@xs4all.nl
Xref csiph.com comp.lang.python:63389

Show key headers only | View raw


[Multipart message — attachments visible in raw view] - view raw

I've been programming for a long while in an event&callback-driven world.
While I am comfortable enough with the mechanisms available (almost 100% of
what I do is in a PyGTK world with its signal mechanism), it's never been
all that satisfying, breaking up my calculations into various pieces, and
thus having my algorithm scattered all over the place.

So, I'm looking for a little guidance. It seems to me that futures,
coroutines, and/or the new Tulip/asyncio package might be my salvation, but
I'm having a bit of trouble seeing exactly how that would work. Let me
outline a simple hypothetical calculation. I'm looking for ways in which
these new facilities might improve the structure of my code.

Let's say I have a dead simple GUI with two buttons labeled, "Do A" and "Do
B". Each corresponds to executing a particular activity, A or B, which take
some non-zero amount of time to complete (as perceived by the user) or
cancel (as perceived by the state of the running system - not safe to run A
until B is complete/canceled, and vice versa). The user, being the fickle
sort that he is, might change his mind while A is running, and decide to
execute B instead. (The roles can also be reversed.) If s/he wants to run
task A, task B must be canceled or allowed to complete before A can be
started. Logically, the code looks something like (I fear Gmail is going to
destroy my indentation):

def do_A():
when B is complete, _do_A()
cancel_B()

def do_B():
when A is complete, _do_B()
cancel_A()

def _do_A():
do the real A work here, we are guaranteed B is no longer running

def _do_B():
do the real B work here, we are guaranteed A is no longer running

cancel_A and cancel_B might be no-ops, in which case they need to start up
the other calculation immediately, if one is pending.

This is pretty simple execution, and if my job was this simple, I'd
probably just keep doing things the way I do now, which is basically to
catch a "complete" or "canceled" signal from the A and B tasks and execute
the opposite task if it's pending. But it's not this simple. In reality
there are lots of, "oh, you want to do X? You need to make sure A, B, and C
are not active." And other stuff like that.

I have this notion that I should be able to write do_A() something like
this:

def do_A():
cancel_B()
yield from ... ???
_do_A()
...

or

def do_A():
future = cancel_B()
future.on_completion(_do_A)
... or ???

with the obvious similar structure for do_B. To my mind's eye, the first
option is preferable, since it's obvious that when control reaches the line
after the yield from statement, it's fine to do the guts of task A.

So, is my simpleminded view of the world a possibility with the current
facilities available in 3.3 or 3.4?

Thx,

Skip

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Trying to wrap my head around futures and coroutines Skip Montanaro <skip.montanaro@gmail.com> - 2014-01-06 18:56 -0600

csiph-web