2007-08-21

 

Python Cookbook 3.11 调度命令

需求:

你需要在特定的时间调度命令的执行.

讨论:

标准库中的sched库可以完成这个功能:

import time, os, sys, sched
schedule = sched.scheduler(time.time, time.sleep)
def perform_command(cmd, inc):
schedule.enter(inc, 0, perform_command, (cmd, inc)) # re-scheduler
os.system(cmd)
def main(cmd, inc=60):
schedule.enter (0, 0, perform_command, (cmd, inc)) # 0==right now
schedule.run( )
if _ _name_ _ == '_ _main_ _' :
numargs = len(sys.argv) - 1
if numargs < 1 or numargs > 2:
print "usage: " + sys.argv[0] + " command [seconds_delay]"
sys.exit(1)
cmd = sys.argv[1]
if numargs < 3:
main(cmd)
else:
inc = int(sys.argv[2])
main(cmd, inc)
本节和上节完成了类似的功能,不同的是,上节用自己实现代码的方式,而本节使用sched库来完成.
sched很简单,强大和灵活.使用sched调度的任务在给定时间一定会执行.要使用sched,你首先创建scheduler对象,比如schedule,并包含两个参数.第一个参数用于查找当前时间,它返回一个从标准时间到现在的整数,我们通常称为epoch.第二个参数用于表示延迟多少时间.你可以使用人工的方法来判断时间,比如,使用sched做为模拟程序,当然,手动使用sched衡量时间是高阶应用,在这里不做讨论.
一点你拥有了scheduler对象s,你可以通过s.enter来调度任务,让该任务在N秒后执行(可以传递0,表示立刻执行),也可以是使用s.enterabs,用于设定一个绝对时间.无论那种情况,你传递一个时间(绝对或相对),一个优先级(如果同时有多个任务执行,低优先级的先执行),要执行的函数,还有一个元组表示调用函数的参数.上面两个方法都返回一个事件标识符,一个随机的标识符,用于后来使用s.cancel来取消它.
当完成调度后, 你可以使用s.run来执行,它一直会执行到调度队列为空.在本节中,我们演示了如何调度一个周期执行的事件,函数perform_command做的第一件事情就是重新调度事件,然后再执行.这样做,调度队列永不会为空,而且perform_command函数会被定期执行,在这个函数中,自调度是一个非常重要的写法,不但在sched中,在其它的地方,如果你希望一个事件一旦触发,就会周期的进行,可以使用这个方法.
尽管本节只描述了一个简单的例子,sched依然具有一些有点, 相对于自己写代码来说.在上一节,在cmd执行的期间,需要delay一段时间,假如cmd需要等待的时间是个变量(这也是最常见的情况,比如等待网络,或者比较繁忙的服务等),那么这个任务就不是绝对的周期执行.在本节中,延迟是在cmd执行之前来决定的,所以周期能够保证.如果运行cmd的时间偶尔超过了inc的值,调度会暂时的落后,但很快会在后面赶上,只要cmd的平均运行时间小于inc:sched不会漏掉事件(如果你需要放弃一些事件,使用sched.cancel ).

相关说明:

sched.scheduler.enter(self, delay, priority, action, argument) unbound sched.scheduler method
    A variant that specifies the time as a relative time.

    This is actually the more commonly used interface.

sched.scheduler.enterabs(self, time, priority, action, argument) unbound sched.scheduler method
    Enter a new event in the queue at an absolute time.

    Returns an ID for the event which can be used to remove it,
    if necessary.

sched.scheduler.run(self) unbound sched.scheduler method
    Execute events until the queue is empty.

    When there is a positive delay until the first event, the delay function is called and the event is left in the queue; otherwise, the event is removed from the queue and executed (its action function is called, passing it the argument).  If  the delay function returns prematurely, it is simply restarted.

    It is legal for both the delay function and the action function to to modify the queue or to raise an exception; exceptions are not caught but the scheduler's state remains well-defined so run() may be called again.

    A questionably hack is added to allow other threads to run: just after an event is executed, a delay of 0 is executed, to avoid monopolizing the CPU when other threads are also   runnable.

sched.scheduler.cancel(self, event) unbound sched.scheduler method
    Remove an event from the queue.

    This must be presented the ID as returned by enter(). If the event is not in the queue, this raises RuntimeError.

标签:


Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?