Reputation: 500
this is a timer inside a game I programmed:
def function(event):
time.sleep(.2)
tx2 = time.time()
if tx2-tx1 > 0.7:
#do the repetitive stuff here
return function(1)
tx1 = time.time()
thread.start_new_thread(function,(1,))
is there a better way to write this? to me it seems a bit dirty calling a recursive function and a new thread... moreover it crashes after a while...
Upvotes: 0
Views: 4912
Reputation: 92559
Your current example runs into the issue of recursion limits, because of the way it calls itself recursively. The stack size continues to grow and grow until it hits the default 1000, most likely. See this modified example:
import time
import inspect
import thread
tx1 = time.time()
def loop(event):
print "Stack size: %d" % len(inspect.stack())
tx2 = time.time()
if tx2-tx1 > 0.7:
print "Running code."
return loop(1)
thread.start_new_thread(loop, (1,))
time.sleep(60)
## OUTPUT ##
Stack size: 1
Running code.
Stack size: 2
Running code.
...
Stack size: 999
Running code.
Exception RuntimeError: 'maximum recursion depth exceeded in ...
Its probably easiest to use a custom Thread class that can run until you tell it to stop. This way the stack size doesn't keep growing. It just loops and calls your handler function. Here is a working complete example:
import time
from threading import Thread
class IntervalTimer(Thread):
def __init__(self, secs, func, args=(), kwargs={}):
super(IntervalTimer, self).__init__(target=func, args=args, kwargs=kwargs)
self.__interval = secs
self.__func = func
self.__args = args
self.__kwargs = kwargs
self.__exiting = False
def run(self):
while not self.__exiting:
time.sleep(self.__interval)
self.__func(*self.__args, **self.__kwargs)
def cancel(self):
self.__exiting = True
def test(val):
print val
if __name__ == "__main__":
t = IntervalTimer(2, test, args=("Hi",))
t.start()
time.sleep(10)
t.cancel()
Upvotes: 3