python之sched

sched是python的任务调度类库。所谓任务调度,就是根据任务的先后及优先级顺序执行。sched的使用这里就不介绍了,大家可以参考官方文档(https://docs.python.org/2.6/library/sched.html)。本文的重点将介绍sched的内部运作原理。

sched内部原理

sched是类库的名称,实际上,sched内部封装了一个scheduler类,用于负责任务的新增、取消、执行等操作。
scheduler内部结构如下图:
这里写图片描述

下面将着重分析__init__enterabsentercancelrun函数功能。

_init_

def __init__(self, timefunc, delayfunc):
    #任务列表
    self._queue = []
    #时间函数,相当于计时器功能
    self.timefunc = timefunc
    #延迟函数,任务推迟执行前调用
    self.delayfunc = delayfunc

从上面的代码可以看出,__init__ 定义了3个属性:_queue、timefunc、delayfunc ,其中timefuncdelayfunc 由用户定义时传递。内部使用数组来存储任务信息,那么事件的新增、取消等功能,实际上都是对数组的处理操作。

enterabs

#time : 时间戳
#priority : 优先级,值越小,优先级越高
#action :  回调事件函数
#argument : 回调事件函数参数
def enterabs(self, time, priority, action, argument):
    //构建事件对象
    event = Event(time, priority, action, argument)
    heapq.heappush(self._queue, event)
    return event

**enterabs() 非常适合定时任务的业务场景,我们可以通过它新增一个事件。
其中,Event 对象是内部自定义的事件结构,代码如下:

from collections import namedtuple
Event = namedtuple('Event', 'time, priority, action, argument')

值得注意的是heapq.heappush(self._queue, event) 这行代码。heapq 是 python的堆排序类库。这行代码实现了将event添加至self._queue,且进行堆排序的功能。 (至于为什么使用堆排序,读者可以思考下)

enter

#delay:推迟执行的时间
#priority:优先级
#action:回调事件函数
#argument:回调事件函数参数
def enter(self, delay, priority, action, argument):
    time = self.timefunc() + delay
    return self.enterabs(time, priority, action, argument)

从上面的代码可以看出,enter() 内部调用 enterabs() 。两者差异微妙,只是应用场景不同。enter()第一个参数代表任务推迟执行的时间。

cancel

#event:目标事件
def cancel(self, event):
    self._queue.remove(event)
    heapq.heapify(self._queue)

cancel() :用于取消事件功能。 系统首先会将_queue的event移除,然后调用heapq.heapify() 对_queue剩下的元素排序,保证时间最近优先级最高的事件放在首位。

run

def run(self):
    #...省略部分代码...
    while q:
        time, priority, action, argument = checked_event = q[0]
        now = timefunc()
        #判断是否已到达任务执行事件
        if now < time:
            #若未到达,则调用delayfunc函数推迟执行。
            delayfunc(time - now)
        else:
            #取出事件
            event = pop(q)          
            #判断事件是否发生变化
            if event is checked_event:
                #执行事件,回调事件函数
                action(*argument)
                delayfunc(0)
            else:
                #如果发生变化,则将事件添加到列表中
                heapq.heappush(q, event)

run()执行时会发生阻塞,直到所有事件都执行完毕。由于事件执行前,queue的第一个事件可能发生变化,so 需判断事件的一致性。

总结

  1. sched内部使用“数组对象”来保存任务列表。通过堆排序来实现”时间+优先级”算法.
  2. sched的run()函数执行会发生阻塞,直到任务全部运行完毕。当run()运行时,可考虑通过异步方式添加或取消任务。例如:多线程
  3. sched设计简单、灵活;但缺乏安全性。需结合自己的业务场景考虑是否采用。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值