From the way you've defined your problem, I think this is a good situation for using a generator based co-routine. That is, change myFunction
to a generator that yield
s every time it has finished with a step of its processing (e.g. do1
or do2
) and run it from a loop that checks the time.
Here's a simple implementation that repeatedly runs a single somework
function, but you could easily call different functions, or even do work directly in the myFunction
generator:
import time
def somework():
print "Doing some work!"
time.sleep(2)
def myFunction():
try:
print "Started myFunction()"
yield somework()
yield somework()
yield somework()
yield somework()
yield somework()
print "Done with myFunction()"
except GeneratorExit:
print "Exiting myFunction() early!"
def main():
start = time.time()
gen = myFunction()
for _ in gen:
if time.time() > start+5:
gen.close();
There are some benefits to using this structure:
- First off,
myFunction
gets to choose where it yield
s to the outer loop, so it won't get killed at an unexpected time. If it's manipulating some external data structure, you can ensure it always yields with everything in a consistent state.
- Second,
myFunction
can yield intermediate values, if that is useful. The example code above yields None
(since that's the return value from somework
but you can change that easily. The main loop puts the latest yielded value in the _
variable (which is not used), but you can rename that variable and use its value in the timeout block if you want.
- Finally, by catching the
GeneratorExit
exception, myFunction
can run any cleanup code that it needs before it shuts down.