Pella86
Pella86

Reputation: 500

Timer in Python for a Game

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

Answers (1)

jdi
jdi

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

Related Questions