At the end of foo(), create a Timer which calls foo() itself after 10 seconds.
Because, Timer create a new thread to call foo().
You can do other stuff without being blocked.
import time, threading
def foo():
print(time.ctime())
threading.Timer(10, foo).start()
foo()
#output:
#Thu Dec 22 14:46:08 2011
#Thu Dec 22 14:46:18 2011
#Thu Dec 22 14:46:28 2011
#Thu Dec 22 14:46:38 2011
Answer from kev on Stack OverflowAt the end of foo(), create a Timer which calls foo() itself after 10 seconds.
Because, Timer create a new thread to call foo().
You can do other stuff without being blocked.
import time, threading
def foo():
print(time.ctime())
threading.Timer(10, foo).start()
foo()
#output:
#Thu Dec 22 14:46:08 2011
#Thu Dec 22 14:46:18 2011
#Thu Dec 22 14:46:28 2011
#Thu Dec 22 14:46:38 2011
Simply sleeping for 10 seconds or using threading.Timer(10,foo) will result in start time drift. (You may not care about this, or it may be a significant source of problems depending on your exact situation.) There can be two causes for this - inaccuracies in the wake up time of your thread or execution time for your function.
You can see some results at the end of this post, but first an example of how to fix it. You need to track when your function should next be called as opposed to when it actually got called and account for the difference.
Here's a version that drifts slightly:
import datetime, threading
def foo():
print datetime.datetime.now()
threading.Timer(1, foo).start()
foo()
Its output looks like this:
2013-08-12 13:05:36.483580
2013-08-12 13:05:37.484931
2013-08-12 13:05:38.485505
2013-08-12 13:05:39.486945
2013-08-12 13:05:40.488386
2013-08-12 13:05:41.489819
2013-08-12 13:05:42.491202
2013-08-12 13:05:43.492486
2013-08-12 13:05:44.493865
2013-08-12 13:05:45.494987
2013-08-12 13:05:46.496479
2013-08-12 13:05:47.497824
2013-08-12 13:05:48.499286
2013-08-12 13:05:49.500232
You can see that the sub-second count is constantly increasing and thus, the start time is "drifting".
This is code that correctly accounts for drift:
import datetime, threading, time
next_call = time.time()
def foo():
global next_call
print datetime.datetime.now()
next_call = next_call+1
threading.Timer( next_call - time.time(), foo ).start()
foo()
Its output looks like this:
2013-08-12 13:21:45.292565
2013-08-12 13:21:47.293000
2013-08-12 13:21:48.293939
2013-08-12 13:21:49.293327
2013-08-12 13:21:50.293883
2013-08-12 13:21:51.293070
2013-08-12 13:21:52.293393
Here you can see that there is no longer any increase in the sub-second times.
If your events are occurring really frequently you may want to run the timer in a single thread, rather than starting a new thread for each event. While accounting for drift this would look like:
import datetime, threading, time
def foo():
next_call = time.time()
while True:
print datetime.datetime.now()
next_call = next_call+1;
time.sleep(next_call - time.time())
timerThread = threading.Thread(target=foo)
timerThread.start()
However your application will not exit normally, you'll need to kill the timer thread. If you want to exit normally when your application is done, without manually killing the thread, you should use
timerThread = threading.Thread(target=foo)
timerThread.daemon = True
timerThread.start()
Timer expects a sequence (normally, a list or tuple) of arguments and a mapping (normally, a dict) of keyword arguments, so pass a list instead:
import threading
def hello(arg):
print(arg)
t = threading.Timer(2, hello, ["bb"])
t.start()
while 1:
pass
Since "bb" is an iterable, the Timer will iterate over it and use each element as a separate argument; threading.Timer(2, hello, "bb") is equivalent to threading.Timer(2, hello, ["b", "b"]).
Use a dictionary to pass any keyword arguments to the callback, for example:
def hello(arg, kwarg):
print('arg is', arg, 'and kwarg is', kwarg)
t = threading.Timer(2, hello, ["bb"], {'kwarg': 1})
The third argument to Timer is a sequence. Passing "bb" as that sequence means that hello gets the elements of that sequence ("b" and "b") as separate arguments (arg and kargs). Put "bb" in a list, and hello will get the string as the first argument:
t = threading.Timer(2, hello, ["bb"])
Presumably, hello was intended to have parameters like:
def hello(*args, **kwargs):
See What does ** (double star/asterisk) and * (star/asterisk) do for parameters? for a detailed explanation of this syntax.
You should use the thread.join() to wait until your timer's thread is really finished and cleaned.
import threading
def ontimer():
print threading.current_thread()
def main():
timer = threading.Timer(2, ontimer)
timer.start()
print threading.current_thread()
timer.cancel()
timer.join() # here you block the main thread until the timer is completely stopped
if timer.isAlive():
print "Timer is still alive"
else:
print "Timer is no more alive"
if timer.finished:
print "Timer is finished"
if __name__ == "__main__":
main()
This will display :
<_MainThread(MainThread, started 5836)>
Timer is no more alive
Timer is finished
A Timer is a subclass of a Thread and its implementation is really simple. It waits the provided time by subscribing to the event finished.
So when you set the event by Timer.cancel it is guaranteed that the function does not get called. But it is not guaranteed that the Timer thread will directly continue (and exit).
So the point is that the thread of the timer can still be alive after the execution of cancel, but the function will not get executed. So checking for finished is safe, while testing for Thread.is_alive (newer API, use this!) is a race condition in this case.
Hint: You can verify this by placing a time.sleep after calling cancel. Then it will just print:
<_MainThread(MainThread, started 10872)>
Timer is finished
The best way is to start the timer thread once. Inside your timer thread you'd code the following
class MyThread(Thread):
def __init__(self, event):
Thread.__init__(self)
self.stopped = event
def run(self):
while not self.stopped.wait(0.5):
print("my thread")
# call a function
In the code that started the timer, you can then set the stopped event to stop the timer.
stopFlag = Event()
thread = MyThread(stopFlag)
thread.start()
# this will stop the timer
stopFlag.set()
Improving a little on Hans Then's answer, we can just subclass the Timer function. The following becomes our entire "repeat timer" code, and it can be used as a drop-in replacement for threading.Timer with all the same arguments:
from threading import Timer
class RepeatTimer(Timer):
def run(self):
while not self.finished.wait(self.interval):
self.function(*self.args, **self.kwargs)
Usage example:
def dummyfn(msg="foo"):
print(msg)
timer = RepeatTimer(1, dummyfn)
timer.start()
time.sleep(5)
timer.cancel()
produces the following output:
foo
foo
foo
foo
and
timer = RepeatTimer(1, dummyfn, args=("bar",))
timer.start()
time.sleep(5)
timer.cancel()
produces
bar
bar
bar
bar
You would call the cancel method after you start the timer:
import time
import threading
def hello():
print "hello, world"
time.sleep(2)
t = threading.Timer(3.0, hello)
t.start()
var = 'something'
if var == 'something':
t.cancel()
You might consider using a while-loop on a Thread, instead of using a Timer.
Here is an example appropriated from Nikolaus Gradwohl's answer to another question:
import threading
import time
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.count = 10
def run(self):
while self.count > 0 and not self.event.is_set():
print self.count
self.count -= 1
self.event.wait(1)
def stop(self):
self.event.set()
tmr = TimerClass()
tmr.start()
time.sleep(3)
tmr.stop()
I'm not sure if I understand correctly. Do you want to write something like in this example?
>>> import threading
>>> t = None
>>>
>>> def sayHello():
... global t
... print "Hello!"
... t = threading.Timer(0.5, sayHello)
... t.start()
...
>>> sayHello()
Hello!
Hello!
Hello!
Hello!
Hello!
>>> t.cancel()
>>>
Try this:
t = threading.Timer(30.0, self.continousUpdate, [contractId],{} )
When you read self.continuousUpdate, the method is already bound to the object, even if you don't call it yet. You don't need to pass self again.
The reason the second version "ignores the thread" is that you call the method inside an argument to the Timer call, so it runs (and tries to call itself again) before the Timer ever gets started. That's why threading functions have you pass the function and its arguments separately (so it can call the function itself when it's ready).
Incidentally, you spelled "continuous" wrong.
Just remove the self parameter.
Here is a full working solution:
import threading
class DataCollect():
def __init__(self):
pass
def hello(self):
print("hello, world")
t = threading.Timer(5.0, self.hello)
t.start()
dataCollect = DataCollect()
dataCollect.hello()