我想知道python threading.Timer
是如何工作的。
更详细地说,当我运行几个threading.Timer
时,是否运行单独的线程来计算时间并运行处理程序?
或者一个线程一起管理和计算几个计时器?
我在问,因为我的申请需要安排很多活动,但是
如果threading.Timer分别运行每个线程来计算一个计时器,并且我运行很多计时器,它可能会影响性能。
所以我担心如果我必须实现只运行一个线程的调度程序,如果它对性能有很大影响。
答案 0 :(得分:4)
threading.Timer
类是threading.Thread
的子类,基本上它只运行一个单独的线程,在该线程中它会睡眠指定的时间并运行相应的函数。
绝对不是安排活动的有效方式。更好的方法是使用Queue.PriorityQueue
在一个线程中进行调度,您可以在其中将事件放在" priority"实际上意味着"下一个开火日期"。与cron的工作方式类似。
甚至更好:使用已经存在的东西,不要重新发明轮子:Cron,Celery,等等......
通过Queue.PriorityQueue
制作调度程序的一个非常简单的示例:
import time
from Queue import PriorityQueue
class Task(object):
def __init__(self, fn, crontab):
# TODO: it should be possible to pass args, kwargs
# so that fn can be called with fn(*args, **kwargs)
self.fn = fn
self.crontab = crontab
def get_next_fire_date(self):
# TODO: evaluate next fire date based on self.crontab
pass
class Scheduler(object):
def __init__(self):
self.event_queue = PriorityQueue()
self.new_task = False
def schedule_task(self, fn, crontab):
# TODO: add scheduling language, crontab or something
task = Task(fn, crontab)
next_fire = task.get_next_fire_date()
if next_fire:
self.new_task = True
self.event_queue.put((next_fire, task))
def run(self):
self.new_task = False
# TODO: do we really want an infinite loop?
while True:
# TODO: actually we want .get() with timeout and to handle
# the case when the queue is empty
next_fire, task = self.event_queue.get()
# incremental sleep so that we can check
# if new tasks arrived in the meantime
sleep_for = int(next_fire - time.time())
for _ in xrange(sleep_for):
time.sleep(1)
if self.new_task:
self.new_task = False
self.event_queue.put((next_fire, task))
continue
# TODO: run in separate thread?
task.fn()
time.sleep(1)
next_fire = task.get_next_fire_date()
if next_fire:
event_queue.put((next_fire, task))
def test():
return 'hello world'
sch = Scheduler()
sch.schedule_task(test, '5 * * * *')
sch.schedule_task(test, '0 22 * * 1-5')
sch.schedule_task(test, '1 1 * * *')
sch.run()
这只是一个想法。您必须正确实现Task
和Scheduler
类,即get_next_fire_date
方法加上某种调度语言(crontab?)和错误处理。我仍然强烈建议使用现有的一个库。
答案 1 :(得分:0)
来自CPython 2.7来源:
def Timer(*args, **kwargs):
"""Factory function to create a Timer object.
Timers call a function after a specified number of seconds:
t = Timer(30.0, f, args=[], kwargs={})
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
return _Timer(*args, **kwargs)
class _Timer(Thread):
"""Call a function after a specified number of seconds:
t = Timer(30.0, f, args=[], kwargs={})
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
def __init__(self, interval, function, args=[], kwargs={}):
Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.finished = Event()
def cancel(self):
"""Stop the timer if it hasn't finished yet"""
self.finished.set()
def run(self):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.set()
正如在另一个答案中所说,它是一个单独的线程(因为它是Thread的子类)。计时器用完时的回调函数从新线程调用。