Skip to content

Instantly share code, notes, and snippets.

@dstuebe
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstuebe/07cb01b13e4f46071565 to your computer and use it in GitHub Desktop.
Save dstuebe/07cb01b13e4f46071565 to your computer and use it in GitHub Desktop.
Chaining coroutines for number crunching workflows...
TARGETS = 'targets'
class AnalysisWindowComplete(Exception):
"""
Used in coroutine control flow, this is not an error condition.
"""
def coroutine(func):
"""
Decorator function for coroutines to automatically call next so that they are in
a ready state when they are called. (from dabeaz)
"""
def start(*args, **kwargs):
g = func(*args, **kwargs)
g.next()
return g
return start
@coroutine
def myprinter(name):
while True:
p = (yield)
print "printer %s says: %s" % (name, p)
@coroutine
def average(targets):
result = 0.0
try:
while True:
cnt = 0
try:
while True:
val = (yield)
result += val
cnt += 1
except AnalysisWindowComplete as wc:
print 'In finalize with:', wc
result = result/cnt
for target in targets:
target.send(result)
result = 0.0
except (ValueError, IndexError) as e:
raise
def get_targets(co):
try:
return co.gi_frame.f_locals[TARGETS]
except KeyError as ke:
print 'foo bar muck up...'
def set_targets(co, targets):
t = get_targets(co)
while len(t) > 0:
t.pop()
for target in targets:
t.append(target)
avg_co = average([myprinter('Initial...'),] )
avg_co.send(5.)
avg_co.send(5.)
avg_co.send(5.)
avg_co.send(4.)
avg_co.throw(AnalysisWindowComplete,'foo')
# Now continue using the same coroutine workflow for next analysis
avg_co.send(6)
avg_co.send(6)
avg_co.send(7)
# change where things go...
set_targets(avg_co,(myprinter('barbaz'),myprinter('boo')) )
avg_co.throw(AnalysisWindowComplete,'goo')
# but if you want to chain these - you spend a lot of time calling throw and creating exceptions!
# maybe try a class decorator to memoize __init__ for the exception?
# maybe try an allocation pool?
# or just make sure your program spends way more time in the main part of the workflow that uses send...
# If you are using this to throw all the time your doing it wrong.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment