Python的等价的setInterval()?
Python有一个类似于JavaScript的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
sched
模块为通用Python代码提供了这些function。 但是,正如其文档所示,如果您的代码是multithreading的,那么使用threading.Timer
类可能更有意义。
我想这是你以后的事情:
#timertest.py import sched, time def dostuff(): print "stuff is being done!" s.enter(3, 1, dostuff, ()) s = sched.scheduler(time.time, time.sleep) s.enter(3, 1, dostuff, ()) s.run()
如果在重复方法的末尾添加另一个条目到调度程序,它将继续。
改变Nailxx的答案,你有答案!
from threading import Timer def hello(): print "hello, world" Timer(30.0, hello).start() Timer(30.0, hello).start() # after 30 seconds, "hello, world" will be printed
只要保持简洁,我不知道为什么所有的答案都使事情变得如此复杂:
import threading def setInterval(func,time): e = threading.Event() while not e.wait(time): func() def foo(): print "hello" # using setInterval(foo,5) # output: hello hello . . .
编辑:这段代码是非阻塞的
import threading class ThreadJob(threading.Thread): def __init__(self,callback,event,interval): '''runs the callback function after interval seconds :param callback: callback function to invoke :param event: external event for controlling the update operation :param interval: time in seconds after which are required to fire the callback :type callback: function :type interval: int ''' self.callback = callback self.event = event self.interval = interval super(ThreadJob,self).__init__() def run(self): while not self.event.wait(self.interval): self.callback() event = threading.Event() def foo(): print "hello" k = ThreadJob(foo,event,2) k.start() print "It is non-blocking"
来自Python文档 :
from threading import Timer def hello(): print "hello, world" t = Timer(30.0, hello) t.start() # after 30 seconds, "hello, world" will be printed
最近,我和你有同样的问题。 我发现这些解决scheme:
1.你可以使用库: threading.Time (这里有介绍)
2.你可以使用库: sched (这个也有介绍)
3.你可以使用库: Advanced Python Scheduler (推荐)
上面的方法并不完全适合我,因为我需要能够取消间隔。 我把这个function变成了一个class级,并提出了以下内容:
class setInterval(): def __init__(self, func, sec): def func_wrapper(): self.t = threading.Timer(sec, func_wrapper) self.t.start() func() self.t = threading.Timer(sec, func_wrapper) self.t.start() def cancel(self): self.t.cancel()
上面的一些答案使用func_wrapper
和threading.Timer
的确是工作,除了它每次调用一个间隔时产生一个新的线程,这是造成内存问题。
下面的基本示例通过将间隔放在单独的线程上大致实现了类似的机制。 它在给定的时间间隔睡觉。 在跳入代码之前,您需要了解以下一些限制:
-
JavaScript是单线程的,所以当
setInterval
里面的函数被触发的时候,没有其他的东西会同时工作(不包括工作线程,但是我们来讨论一下setInterval
一般用例,因此线程是安全的。可能会遇到竞争条件,除非使用threading.rLock
。 -
下面的实现使用
time.sleep
来模拟时间间隔,但增加了func
的执行时间,这个时间间隔的总时间可能会比你期望的要大。 因此,根据使用情况,您可能需要“less睡”(减去调用func
时间) -
我只粗略地testing了一下,你绝对不应该像我那样使用全局variables,随意调整它,使它适合你的系统。
说够了,这里是代码:
# Python 2.7 import threading import time class Interval(object): def __init__(self): self.daemon_alive = True self.thread = None # keep a reference to the thread so that we can "join" def ticktock(self, interval, func): while self.daemon_alive: time.sleep(interval) func() num = 0 def print_num(): global num num += 1 print 'num + 1 = ', num def print_negative_num(): global num print '-num = ', num * -1 intervals = {} # keep track of intervals g_id_counter = 0 # roughly generate ids for intervals def set_interval(interval, func): global g_id_counter interval_obj = Interval() # Put this interval on a new thread t = threading.Thread(target=interval_obj.ticktock, args=(interval, func)) t.setDaemon(True) interval_obj.thread = t t.start() # Register this interval so that we can clear it later # using roughly generated id interval_id = g_id_counter g_id_counter += 1 intervals[interval_id] = interval_obj # return interval id like it does in JavaScript return interval_id def clear_interval(interval_id): # terminate this interval's while loop intervals[interval_id].daemon_alive = False # kill the thread intervals[interval_id].thread.join() # pop out the interval from registry for reusing intervals.pop(interval_id) if __name__ == '__main__': num_interval = set_interval(1, print_num) neg_interval = set_interval(3, print_negative_num) time.sleep(10) # Sleep 10 seconds on main thread to let interval run clear_interval(num_interval) clear_interval(neg_interval) print "- Are intervals all cleared?" time.sleep(3) # check if both intervals are stopped (not printing) print "- Yup, time to get beers"
预期产出:
num + 1 = 1 num + 1 = 2 -num = -2 num + 1 = 3 num + 1 = 4 num + 1 = 5 -num = -5 num + 1 = 6 num + 1 = 7 num + 1 = 8 -num = -8 num + 1 = 9 num + 1 = 10 -num = -10 Are intervals all cleared? Yup, time to get beers
我的Python 3模块jsinterval.py
将有所帮助! 这里是:
""" Threaded intervals and timeouts from JavaScript """ import threading, sys __all__ = ['TIMEOUTS', 'INTERVALS', 'setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'] TIMEOUTS = {} INTERVALS = {} last_timeout_id = 0 last_interval_id = 0 class Timeout: """Class for all timeouts.""" def __init__(self, func, timeout): global last_timeout_id last_timeout_id += 1 self.timeout_id = last_timeout_id TIMEOUTS[str(self.timeout_id)] = self self.func = func self.timeout = timeout self.threadname = 'Timeout #%s' %self.timeout_id def run(self): func = self.func delx = self.__del__ def func_wrapper(): func() delx() self.t = threading.Timer(self.timeout/1000, func_wrapper) self.t.name = self.threadname self.t.start() def __repr__(self): return '<JS Timeout set for %s seconds, launching function %s on timeout reached>' %(self.timeout, repr(self.func)) def __del__(self): self.t.cancel() class Interval: """Class for all intervals.""" def __init__(self, func, interval): global last_interval_id self.interval_id = last_interval_id INTERVALS[str(self.interval_id)] = self last_interval_id += 1 self.func = func self.interval = interval self.threadname = 'Interval #%s' %self.interval_id def run(self): func = self.func interval = self.interval def func_wrapper(): timeout = Timeout(func_wrapper, interval) self.timeout = timeout timeout.run() func() self.t = threading.Timer(self.interval/1000, func_wrapper) self.t.name = self.threadname self.t.run() def __repr__(self): return '<JS Interval, repeating function %s with interval %s>' %(repr(self.func), self.interval) def __del__(self): self.timeout.__del__() def setInterval(func, interval): """ Create a JS Interval: func is the function to repeat, interval is the interval (in ms) of executing the function. """ temp = Interval(func, interval) temp.run() idx = int(temp.interval_id) del temp return idx def clearInterval(interval_id): try: INTERVALS[str(interval_id)].__del__() del INTERVALS[str(interval_id)] except KeyError: sys.stderr.write('No such interval "Interval #%s"\n' %interval_id) def setTimeout(func, timeout): """ Create a JS Timeout: func is the function to timeout, timeout is the timeout (in ms) of executing the function. """ temp = Timeout(func, timeout) temp.run() idx = int(temp.timeout_id) del temp return idx def clearTimeout(timeout_id): try: TIMEOUTS[str(timeout_id)].__del__() del TIMEOUTS[str(timeout_id)] except KeyError: sys.stderr.write('No such timeout "Timeout #%s"\n' %timeout_id)
编辑代码:修复内存泄漏(由@benjaminz发现)。 现在所有的线程都被清理完了。 为什么会发生这种泄漏? 这是因为隐含的(甚至是明确的)引用。 在我的情况下, TIMEOUTS
和INTERVALS
。 超时自动清除(在此补丁后),因为它们使用调用函数的函数包装,然后自杀。 但是,这是如何发生的? 除非所有引用也被删除,否则对象不能从内存中删除,或者使用gc
模块。 解释:没有办法创build(在我的代码中)对超时/间隔的不需要的引用。 他们只有一个推荐人: TIMEOUTS
/ INTERVALS
TIMEOUTS
。 而且,当中断或完成(只有超时可以完成不间断),他们删除唯一现有的引用自己:他们相应的字典元素。 类使用__all__
完美封装,所以没有内存泄漏的空间。
在Python中,事情的工作方式是不同的:你需要sleep()
(如果你想阻塞当前线程)或者启动一个新的线程。 请参阅http://docs.python.org/library/threading.html