Python 每n秒做一件事而不做while循环?

Python 每n秒做一件事而不做while循环?,python,while-loop,freeze,blender,Python,While Loop,Freeze,Blender,嗯,我正在尝试为Blender编写一个附加组件,我需要每n秒做一件事情,但是,我不能使用while循环,因为它会冻结Blender!!!我该怎么办 import threading def hello(): print "hello, world" t = threading.Timer(30.0, hello) t.start() # after 30 seconds, "hello, world" will be printed 我不太擅长python,也没有尝试过这个

嗯,我正在尝试为Blender编写一个附加组件,我需要每n秒做一件事情,但是,我不能使用while循环,因为它会冻结Blender!!!我该怎么办

import threading

def hello():
   print "hello, world"
   t = threading.Timer(30.0, hello)
   t.start() # after 30 seconds, "hello, world" will be printed
我不太擅长python,也没有尝试过这个。查看这是否有助于您:)

来自Blender API文档:

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

注意:Pythons线程只允许共同货币,不会在多处理器系统上加速脚本,子进程和多进程模块可以与blender一起使用,也可以使用多个CPU

例如:

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
可能会完成这项工作

如果您需要更全面的计划程序,我最喜欢的版本是位于以下位置的配方:

导入线程
导入线程
类操作(线程。\u计时器):
定义初始化(self,*args,**kwargs):
线程。_计时器。uuu初始化uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self.setDaemon(True)
def运行(自):
尽管如此:
self.finished.clear()
self.finished.wait(self.interval)
如果不是self.finished.isSet():
self.function(*self.args,**self.kwargs)
其他:
返回
self.finished.set()
类管理器(对象):
ops=[]
def add_操作(self、operation、interval、args=[],kwargs={}):
op=操作(间隔、操作、参数、kwargs)
self.ops.append(op)
线程。启动新线程(op.run,())
def停止(自):
对于self.ops中的op:
op.取消()
类锁定打印(对象):
定义初始化(自):
self.lock=threading.lock()
def lprint(自身,值):
使用self.lock:
打印值
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
导入时间
导入日期时间
lp=LockPrint()
def hello1():
lp.lprint('{}\thello1!'.format(datetime.datetime.now())
def hello2():
lp.lprint('{}\thello2!'.format(datetime.datetime.now())
def hello3_blocking():#这很糟糕,所以不要在实际代码中这样做;)
lp.lprint('{}\thello3_阻塞开始…')。格式(
datetime.datetime.now()
)),
t=time.time()#获取时间戳
x=0
而time.time()-t<3:#在阻塞循环中迭代3秒
x+=1
lp.lprint('{}\thello3_阻塞完成!({}迭代)').format(
datetime.datetime.now(),x
))
定时器=管理器()
定时器。添加_操作(hello1,1)
定时器。添加_操作(hello2,2)
定时器添加_操作(hello3_阻塞,2)
t0=时间。时间()
当time.time()-t0<10时:
睡眠时间(0.1)
#关掉一切,然后退出。。。
计时器停止()
这通常是时间安全的,因为每个操作都是在一个线程下执行的,所以主线程仍然可以切换出各个操作线程中的阻塞部分,并维护其他操作的时间表(假设您的函数不会一直引发任何异常到解释器,从而中断主调度程序线程…)


我不确定blender将如何运行,但它在我使用过的其他环境(特别是基于tornado的服务器)的非阻塞模式下运行良好

我对python不太了解。但是你不能用定时器和处理程序来解决这个问题!为什么这个问题被解决了?如果你使用Blender,它是完全有效的,并且与编程语言直接相关。堆栈溢出就是这样工作的…:PYes,但我希望它每n秒连续完成一次…值得一提的是你是如何停止的?@Antoni4040将
5.0
替换为
n
@hayden-您可以调用计时器的
cancel
方法-好吧,这只是在5秒后打印,但不是连续打印…@hayden这不是真的。将
threading.activeCount()
添加到
print
语句中,您可以看到最多有3个正在运行的线程(2个在
t.start()
之前,3个在之后):父对象(上一个
hello
),当前正在执行的对象(当前
hello
),以及正在生成的对象(
t.start
)。这段代码的问题是,您无法中断计时器循环,从而迫使用户从外部终止进程。@Nisan.H这仍然是一个相当大的问题……好吧,在每一步对一些线程安全变量添加条件检查以确定循环是否应停止并不困难。这是一个非常基本的计时器,我将uld通常避免在比单个函数无限循环更复杂的情况下以这种特定形式使用它,但它确实有效。当然,我们也可以使用
time.sleep(x)
中为True时:…
循环而不使用线程,因为在本例中它不会增加任何好处。此外,使用外部
线程启动它。Timer(x,hello)
调用将允许您继续运行主辅助线程(例如,脚本的其他部分)与递归繁殖/死亡计时器线程分离。在退出主工作线程之前,您无法控制该线程。
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
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()