2012-11-01 78 views
3

嗯,我正在嘗試爲Blender編寫一個附加組件,並且我需要每n秒執行一次,但是,我無法使用while循環,因爲它凍結了Blender!我該怎麼辦?每隔n秒做一次沒有while循環的事情?

+0

我不太瞭解python。但你不能用一個定時器和一個處理程序! – LivingThing

+1

更多詳情,請... – Antoni4040

+0

爲什麼這個問題關閉?如果您使用Blender並且與編程語言直接相關,則這是完全有效的。 – AMACB

回答

1

從Blender API文檔的Strange errors using ‘threading’ module

Python和Blender的線程,只有當線程完成了腳本執行之前正常工作。例如,使用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 
+0

這真的好像工作... – Antoni4040

-1
import threading 

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

我不是很好用蟒蛇,並沒有試過這個。看看這可以幫助您:)

+0

@hayden這不正確。將'threading.activeCount()'添加到'print'語句中,可以看到至多有3個正在運行的線程(在't.start()'之前2個)和3個之後):父節點(之前的'hello'),一個正在執行(當前'hello'),另一個正在生成('t.start')。這個代碼的問題是你不能跳出定時器循環,迫使用戶從外部終止進程。 –

+0

@ Nisan.H這仍然是一個問題...... –

+0

那麼,在每一步添加一個線程安全變量的條件檢查以確定循環是否應該停止並不是很困難。這是一個非常基本的計時器,我通常會避免以特定的形式使用它,而不是使用比單功能無限循環更復雜的東西,但它確實有效。當然,在沒有線程的情況下,可以在'while True:...'循環中使用'time.sleep(x)',因爲在這個例子中它沒有增加任何好處。 –

3
from threading import Timer 

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

t = Timer(5.0, doSomeThings) # every 5 seconds 
t.start() 
+0

是的,但我希望它每隔n秒連續完成...... – Antoni4040

+0

值得一提的是你如何阻止它? –

+0

@ Antoni4040用'n'替代'5.0'。 –

1

根據您的需求,time.sleepthreading.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() 

這通常是一次安全的,在這個意義上,因爲每次操作一個線程在執行時,主線程仍然可以切換單個操作線程中的阻塞部分,並在其他操作上維護時間表(假設您的函數不會在解釋器一直引發任何異常,打破主調度器線程...)

我不知道這將如何與攪拌機,但它的工作在我使用過的其他環境(特別是基於龍捲風的服務器)時,它處於非阻塞模式。

相關問題