Well, I'm trying to write an add-on for Blender and I need to do something every n seconds, but, I can't use a while loop, because it freezes Blender!!! What do I do?
-
I do not know python well. but cant you do with a Timer and a Handler for that ! – mu_sa Nov 01 '12 at 17:35
-
Why was this question closed? It is perfectly valid if you are using Blender, and is directly related to a programming language. – AMACB Dec 28 '15 at 07:25
-
That's how Stack Overflow works... :P – Antoni4040 Dec 28 '15 at 12:03
4 Answers
from threading import Timer
def doSomeThings():
print "Things are being done"
t = Timer(5.0, doSomeThings) # every 5 seconds
t.start()

- 95,302
- 53
- 242
- 374
-
-
-
-
1@hayden - you can call the `cancel` method of the timer - http://stackoverflow.com/questions/9812344/cancellable-threading-timer-in-python – Buggabill Nov 01 '12 at 20:10
-
1
From Strange errors using ‘threading’ module of the Blender API documentation:
Python threading with Blender only works properly when the threads finish up before the script does. By using threading.join() for example.
Note: Pythons threads only allow co-currency and won’t speed up your scripts on multi-processor systems, the subprocess and multiprocess modules can be used with blender and make use of multiple CPU’s too.
from threading import Thread, Event
class Repeat(Thread):
def __init__(self,delay,function,*args,**kwargs):
Thread.__init__(self)
self.abort = Event()
self.delay = delay
self.args = args
self.kwargs = kwargs
self.function = function
def stop(self):
self.abort.set()
def run(self):
while not self.abort.isSet():
self.function(*self.args,**self.kwargs)
self.abort.wait(self.delay)
Example:
from time import sleep
def do_work(foo):
print "busy", foo
r = Repeat(1,do_work,3.14) # execute do_work(3.14) every second
r.start() # start the thread
sleep(5) # let this demo run for 5s
r.stop() # tell the thread to wake up and stop
r.join() # don't forget to .join() before your script ends

- 1
- 1

- 6,186
- 1
- 23
- 29
Depending on your needs, time.sleep
or threading.Timer
might do the job.
If you need a more comprehensive scheduler, my favourite version is the recipe found at http://code.activestate.com/recipes/496800-event-scheduling-threadingtimer/:
import thread
import threading
class Operation(threading._Timer):
def __init__(self, *args, **kwargs):
threading._Timer.__init__(self, *args, **kwargs)
self.setDaemon(True)
def run(self):
while True:
self.finished.clear()
self.finished.wait(self.interval)
if not self.finished.isSet():
self.function(*self.args, **self.kwargs)
else:
return
self.finished.set()
class Manager(object):
ops = []
def add_operation(self, operation, interval, args=[], kwargs={}):
op = Operation(interval, operation, args, kwargs)
self.ops.append(op)
thread.start_new_thread(op.run, ())
def stop(self):
for op in self.ops:
op.cancel()
class LockPrint(object):
def __init__(self):
self.lock = threading.Lock()
def lprint(self, value):
with self.lock:
print value
if __name__ == '__main__':
import time
import datetime
lp = LockPrint()
def hello1():
lp.lprint('{}\thello1!'.format(datetime.datetime.now()))
def hello2():
lp.lprint('{}\thello2!'.format(datetime.datetime.now()))
def hello3_blocking(): # this is bad, so don't do it in real code ;)
lp.lprint('{}\thello3_blocking starting... '.format(
datetime.datetime.now()
)),
t = time.time() # get a timestamp
x = 0
while time.time() - t < 3: # iterate in a blocking loop for 3 secs
x += 1
lp.lprint('{}\thello3_blocking complete! ({} iterations)'.format(
datetime.datetime.now(), x
))
timer = Manager()
timer.add_operation(hello1, 1)
timer.add_operation(hello2, 2)
timer.add_operation(hello3_blocking, 2)
t0 = time.time()
while time.time() - t0 < 10:
time.sleep(0.1)
# turn off everything and exit...
timer.stop()
This is generally time-safe, in the sense that since every operation is executed under a thread, the main thread can still switch out of blocking sections in individual operation threads and maintain the schedules on the other operations (assuming your functions don't raise any exceptions all the way to the interpreter, breaking the main scheduler thread...)
I'm not sure how this will behave with blender, but it works well in a non-blocking mode with other environments I've used (specifically, tornado based servers.)

- 6,032
- 2
- 26
- 26
import threading
def hello():
print "hello, world"
t = threading.Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
I am not very good with python and havent tried this. See if this helps you :)

- 2,685
- 10
- 39
- 58
-
@hayden that's not true. Adding `threading.activeCount()` to the `print` statement, you can see there are at most 3 running threads (2 before `t.start()` and 3 after): the parent (previous `hello`), the one currently executing (current `hello`), and the one being spawned (`t.start`). The problem with this code is that you can't break out of the timer loop, forcing the user to terminate the process externally. – Nisan.H Nov 01 '12 at 18:26
-
-
Well, it wouldn't be very difficult to add a condition check on some thread-safe variable at each step to determine whether the loop should stop. It's a very basic timer, and I would generally avoid using it in that particular form for anything more complex than a single-function infinite loop, but it does work. Of course, one might just as well use `time.sleep(x)` in a `while True:...` loop without the threading, since it doesn't add any benefit in this example. – Nisan.H Nov 01 '12 at 19:47
-
Also, starting it with an external `threading.Timer(x, hello)` call would allow you to continue running the main worker thread (e.g. other parts of your script) separate from the recursively spawning/dying timer thread. You just wouldn't have any control over that thread until you exit the main worker thread. – Nisan.H Nov 01 '12 at 19:49