4

好吧,我正在尝试为 Blender 编写一个插件,我需要每隔 n 秒做一次,但是,我不能使用 while 循环,因为它会冻结 Blender !!!我该怎么办?

4

4 回答 4

2
from threading import Timer

def doSomeThings():
    print "Things are being done"

t = Timer(5.0, doSomeThings)  # every 5 seconds
t.start()
于 2012-11-01T17:41:17.990 回答
1

取决于您的需要,time.sleep或者threading.Timer可能完成这项工作。

如果您需要更全面的调度程序,我最喜欢的版本是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()

这通常是时间安全的,因为每个操作都在一个线程下执行,所以主线程仍然可以切换出各个操作线程中的阻塞部分并维护其他操作的时间表(假设您的函数不会引发一直到解释器的任何异常,都会破坏主调度程序线程......)

我不确定这将如何与搅拌机一起使用,但它在我使用的其他环境(特别是基于龙卷风的服务器)的非阻塞模式下运行良好。

于 2012-11-01T19:43:01.070 回答
1

从使用Blender API 文档的“线程”模块的奇怪错误中:

仅当线程在脚本完成之前完成时,使用 Blender 的 Python 线程才能正常工作。例如,通过使用 threading.join()。

注意:Pythons 线程只允许并发并且不会在多处理器系统上加速你的脚本,子进程和多进程模块可以与搅拌机一起使用并且也可以使用多个 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
于 2012-11-01T19:25:58.893 回答
-1
import threading

def hello():
   print "hello, world"
   t = threading.Timer(30.0, hello)
   t.start() # after 30 seconds, "hello, world" will be printed

我对 python 不是很好,也没有尝试过。看看这是否对你有帮助:)

于 2012-11-01T17:40:24.083 回答