我最近发布了一个关于如何推迟Python中函数执行的question(类似于Javascript setTimeout
),结果证明这是一个使用threading.Timer
的简单任务(好吧,只要该函数不与其他代码共享状态,但这会在任何事件驱动的环境中产生问题)。
现在我正在努力做得更好并模仿setInterval
。对于那些不熟悉Javascript的人,setInterval
允许每隔x秒重复一次对函数的调用,而不会阻止其他代码的执行。我创建了这个示例装饰器:
import time, threading
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times:
time.sleep(interval)
function(*args, **kwargs)
i += 1
threading.Timer(0, inner_wrap).start()
return wrap
return outer_wrap
使用如下
@setInterval(1, 3)
def foo(a):
print(a)
foo('bar')
# Will print 'bar' 3 times with 1 second delays
在我看来它工作正常。我的问题是
sys.exit()
也不会阻止它,也不会命中Ctrl+c
。阻止它的唯一方法是从外部杀死python进程。我希望能够从主线程发送一个停止回调的信号。但我是一个有线程的初学者 - 我怎么能在他们之间进行交流?编辑如果有人想知道,这是装饰者的最终版本,感谢jd的帮助
import threading
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
stop = threading.Event()
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times and not stop.isSet():
stop.wait(interval)
function(*args, **kwargs)
i += 1
t = threading.Timer(0, inner_wrap)
t.daemon = True
t.start()
return stop
return wrap
return outer_wrap
如上所述,它可以与固定的重复次数一起使用
@setInterval(1, 3)
def foo(a):
print(a)
foo('bar')
# Will print 'bar' 3 times with 1 second delays
或者可以保持运行直到收到停止信号
import time
@setInterval(1)
def foo(a):
print(a)
stopper = foo('bar')
time.sleep(5)
stopper.set()
# It will stop here, after printing 'bar' 5 times.
答案 0 :(得分:10)
你的解决方案对我来说很好。
有几种与线程通信的方法。要命令线程停止,您可以使用threading.Event()
,其中wait()
方法可以使用time.sleep()
代替stop_event = threading.Event()
...
stop_event.wait(1.)
if stop_event.isSet():
return
...
。
daemon
要让您的线程在程序终止时退出,请在调用True
之前将其start()
属性设置为Timer()
。这也适用于threading.Thread
个对象,因为它们是{{1}}的子类。见http://docs.python.org/library/threading.html#threading.Thread.daemon
答案 1 :(得分:2)
使用递归调用Timer可能有点简单:
from threading import Timer
import atexit
class Repeat(object):
count = 0
@staticmethod
def repeat(rep, delay, func):
"repeat func rep times with a delay given in seconds"
if Repeat.count < rep:
# call func, you might want to add args here
func()
Repeat.count += 1
# setup a timer which calls repeat recursively
# again, if you need args for func, you have to add them here
timer = Timer(delay, Repeat.repeat, (rep, delay, func))
# register timer.cancel to stop the timer when you exit the interpreter
atexit.register(timer.cancel)
timer.start()
def foo():
print "bar"
Repeat.repeat(3,2,foo)
atexit
允许用CTRL-C发出停止信号。
答案 2 :(得分:2)
也许这些是python中最简单的setInterval等价物:
import threading
def set_interval(func, sec):
def func_wrapper():
set_interval(func, sec)
func()
t = threading.Timer(sec, func_wrapper)
t.start()
return t
答案 3 :(得分:0)
这个班级间隔
class ali:
def __init__(self):
self.sure = True;
def aliv(self,func,san):
print "ali naber";
self.setInterVal(func, san);
def setInterVal(self,func, san):
# istenilen saniye veya dakika aralığında program calışır.
def func_Calistir():
func(func,san); #calışıcak fonksiyon.
self.t = threading.Timer(san, func_Calistir)
self.t.start()
return self.t
a = ali();
a.setInterVal(a.aliv,5);