嗯,我正在尝试为Blender编写一个插件,我需要每隔n秒执行一些操作,但是我不能使用while循环,因为它会冻结Blender!我该怎么办?
嗯,我正在尝试为Blender编写一个插件,我需要每隔n秒执行一些操作,但是我不能使用while循环,因为它会冻结Blender!我该怎么办?
from threading import Timer
def doSomeThings():
print "Things are being done"
t = Timer(5.0, doSomeThings) # every 5 seconds
t.start()
5.0
替换为 n
。 - Andy Haydencancel
方法 - https://dev59.com/p2kw5IYBdhLWcg3wkLMX - Buggabill来自Blender API文档中“threading”模块使用时出现的奇怪错误:
在Blender中使用Python中的线程,只有在线程在脚本运行之前完成时才能正常工作。例如,可以使用“threading.join()”。
注意: Python的线程仅允许并发,并不会加速多处理器系统上的脚本运行。subprocess和multiprocess模块可以与Blender一起使用,并可利用多个CPU。
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)
例子:
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
time.sleep
或threading.Timer
可能可以胜任。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()
一般来说,这是时间安全的,因为每个操作都在一个线程下执行,主线程仍然可以在单个操作线程中切换出阻塞部分,并维护其他操作的计划(假设您的函数不会引发任何异常直到解释器,打破主调度程序线程...)
我不确定这在blender中的行为如何,但在我使用过的其他环境中(特别是基于tornado的服务器),它以非阻塞模式运行良好。
import threading
def hello():
print "hello, world"
t = threading.Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
我不太擅长Python,也没有尝试过这个。看看这是否能帮到你 :)
threading.activeCount()
添加到 print
语句中,您可以看到最多有 3 个正在运行的线程(在 t.start()
之前有 2 个,在之后有 3 个):父线程(之前的 hello
),当前正在执行的线程(当前的 hello
)和正在生成的线程(t.start
)。这段代码的问题在于无法跳出计时器循环,强制用户在外部终止进程。 - Nisan.Hwhile True:...
循环中使用time.sleep(x)
而不需要线程,因为它在这个例子中没有任何好处。 - Nisan.Hthreading.Timer(x, hello)
调用来启动它,可以让你继续运行主工作线程(例如脚本的其他部分),与递归生成/死亡的计时器线程分开。但在退出主工作线程之前,你将无法控制该线程。 - Nisan.H