多个周期性定时器

3 投票
2 回答
4207 浏览
提问于 2025-04-15 13:18

有没有什么标准的Python模块可以用来创建多个定时器?我想设计一个系统,能够在一个线程里同时运行多个不同时间间隔的定时器。这个系统还应该能在任何时候取消某个特定的定时器。

提前感谢大家的建议!

2 个回答

2

如果你只能使用一个线程,那就需要维护一个任务列表,里面记录每个任务的执行频率和应该调用哪个函数:

import time

def example1():
    print 'Example'

class Task(object):
    def __init__(self, func, delay, args=()):
        self.args = args
        self.function = func
        self.delay = delay
        self.next_run = time.time() + self.delay

    def shouldRun(self):
        return time.time() >= self.next_run

    def run(self):
        self.function(*(self.args))
        self.next_run += self.delay
        # self.next_run = time.time() + self.delay

tasks = [Task(example1, 1)] # Run example1 every second
while True:
    for t in tasks:
        if t.shouldRun():
            t.run()
        time.sleep(0.01)

或者你可以看看stackless,这个工具非常适合你想做的事情,它可以让你比上面的调度器更细致地切换任务。

6

可以看看Python标准库里的sched模块。这个模块本身并不直接支持定时器,它只处理一次性的“事件”。不过,有个常用的方法可以把一次性事件变成定时器:就是让处理这个一次性事件的函数在完成工作之前,先把自己重新安排到下次执行的时间。

为了更好地管理这个“定时周期性计时器”,可以定义一个类,把关键的概念封装起来:

class spt(object):

  def __init__(self, scheduler, period):
    self._sched = scheduler
    self._period = period
    self._event = None

  def start(self):
    self._event = self._sched.enter(0, 0, self._action, ())

  def _action(self):
    self._event - self._sched.enter(self._period, 0, self._action, ())
    self.act()

  def act(self):
    print "hi there"

  def cancel(self):
    self._sched.cancel(self._event)

要给这个定时周期性计时器关联一个有意义的动作,可以创建一个子类,继承自spt,并重写act方法(这是一种模板方法设计模式)。当然,你也可以选择更灵活的结构,比如让__init__方法接受一个可调用的函数和参数,以及一个调度器(也就是self.scheduler的实例)和一个周期(以秒为单位的浮点数,如果你按照标准方式用time.time和time.sleep来实例化调度器的话);另外,你可能还想设置一个优先级(可以默认值为0),而不是像我上面用的那样直接用常量0作为优先级。

撰写回答