0

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...

Pella86
  • 500
  • 3
  • 10
  • 18
  • This may help you: http://stackoverflow.com/questions/156330/get-timer-ticks-in-python – GoingTharn Oct 07 '11 at 20:58
  • Are you trying to achieve a delayed timer? In this example, once the time exceeds 0.7, it would constantly run your repetitive code, until you somehow touched the tx1 value again, which would need to be protected because its shared memory – jdi Oct 07 '11 at 21:08
  • @jdi just a timer that after tot milliseconds does the repetitive functions – Pella86 Oct 07 '11 at 21:17

1 Answers1

3

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()
jdi
  • 90,542
  • 19
  • 167
  • 203
  • it doesn't work, I tried to use your syntax... and it doesn't refresh de canvas each .2 seconds, it does it only once... – Pella86 Oct 08 '11 at 09:54
  • @Pella86: I have revised my answer to address this, with more detail about the problem. – jdi Oct 09 '11 at 16:59