Python任务调度之sched

  

我们经常需要定时的执行某个任务,在Linux下我们有强大的crontab,但是在Python这个粒度(定时执行函数),如何处理呢?
除了第三方的模块外,标准库为我们提供了sched模块和Timer类。

先说sched模块,准确的说,它是一个调度(延时处理机制),每次想要定时执行某任务都必须写入一个调度。
使用步骤如下:
(1)生成调度器:
s = sched.scheduler(time.time,time.sleep)
第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。可以说sched模块设计者是“在下很大的一盘棋”,比如第一个函数可以是自定义的一个函数,不一定是时间戳,第二个也可以是阻塞socket等。
(2)加入调度事件
其实有enter、enterabs等等,我们以enter为例子。
s.enter(x1,x2,x3,x4)
四个参数分别为:间隔事件、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数,给他的参数(注意:一定要以tuple给如,如果只有一个参数就(xx,))
(3)运行
s.run()
注意sched模块不是循环的,一次调度被执行后就Over了,如果想再执行,请再次enter

import time,sched

#被调度触发的函数
def event_func(msg):
    print "Current Time:",time.time(),'msg:',msg

if __name__ == "__main__":
    #初始化sched模块的scheduler类
    s = sched.scheduler(time.time,time.sleep)
    #设置两个调度
    s.enter(1,2,event_func,("Small event.",))
    s.enter(2,1,event_func,("Big event.",))
    s.run()
    while True:
        time.sleep(100)


转自:http://www.coder4.com/archives/1589

 

 

 

 

 

 

  之前写过一篇文章是关于Scheduler框架进行任务调度的,还不了解的同学这里提供链接地址:《Python之Scheduler框架浅析 》

    这次我们主要讲解下Python自带模块当中的sched,不但小巧,也很强大,在实际应用中,某些场合还是可以用到的。作为一名Linux的SA,我们已经习惯了用crontab,而sched提供了一种延迟处理机制,也可以理解为任务调度的另一种方式的实现。

    scheduler.enter(delay, priority, action, argument)

    ● delay:延迟时间

    ● priority:优先级

    ● action:回调函数

    ● argument:回调函数的参数

    我们来写一个非常简单的例子:

import sched 
import time 
 
scheduler = sched.scheduler(time.time, time.sleep) 
 
def func(name): 
    print 'action: %s' % name , time.time() 
 
print 'START:', time.time() 
scheduler.enter(2, 1, func, ('fight',)) 
scheduler.enter(3, 1, func, ('make peace',)) 
 
scheduler.run() 
print 'END:', time.time() 


 

    运行结果如下:

    START: 1339664955.4
    action: fight 1339664957.4
    action: make peace 1339664958.4
    END: 1339664958.4

    我们再举一个简单的例子说明下sched的其它特性:

 

import sched 
import time 
  
scheduler = sched.scheduler(time.time, time.sleep) 
  
def func(name): 
    print 'BEGIN: %s:' % name, time.time() 
    time.sleep(2) 
    print 'FINISH %s:' % name, time.time() 
  
print 'START:', time.time() 
scheduler.enter(2, 1, func, ('fight',)) 
scheduler.enter(3, 1, func, ('make peace',)) 
  
scheduler.run() 
print 'END:', time.time() 


 

    运行结果如下:

    START: 1339665268.12
    BEGIN: fight: 1339665270.12
    FINISH fight: 1339665272.12
    BEGIN: make peace: 1339665272.12
    FINISH make peace: 1339665274.12
    END: 1339665274.12

    我们仔细观察下两次任务调度的时间间隔,发现是同时运行的?那又是为什么呢?run()一直被阻塞,直到所有事件被全部执行完. 每个事件在同一线程中运行,所以如果一个事件的执行时间大于其他事件的延迟时间,那么,就会产生重叠。重叠的解决方法是推迟后来事件的执行时间。这样保证没有丢失任何事件,但这些事件的调用时刻会比原先设定的迟。

    上面的例子第二个事件在第一个事件运行结束后立即运行,因为第一个事件的执行时间足够长,已经超过第二个事件的预期开始时刻。(本来应该1339660903秒运行)

    我们再介绍另外一个保证action在同一时刻执行的函数:

    scheduler.enterabs(time, priority, action, argument)

 

 

 

import sched 
import time 
 
scheduler = sched.scheduler(time.time, time.sleep) 
now = time.time() 
 
def func(name): 
    print 'action:', time.time(), name 
 
print 'START:', now 
scheduler.enterabs(now + 2, 2, func, ('make peace',)) 
scheduler.enterabs(now + 2, 1, func, ('fight',)) 
scheduler.run() 
print 'END:', now 


 

    运行结果如下:

    START: 1339666232.38
    action: 1339666234.38 fight
    action: 1339666234.38 make peace
    END: 1339666232.38

    因为优先级的关系,所以先fight,然后再make peace,打架是如此重要....总体来讲,如果想单纯的替换crontab的话,Scheduler框架更加适合,做延迟任务的调度处理的话sched还是可以考虑的。

    如果我们想要取消任务调度,可以使用cancel()函数。在上面的例子中出现了阻塞延迟的现象,如果引用线程机制就会避免这种情况的发生,我们简单举个例子:

import sched 
import threading 
import time 
 
scheduler = sched.scheduler(time.time, time.sleep) 
 
counter = 0 
 
def increment_counter(name): 
 
    global counter 
    print 'action: %s' % name , time.time() 
    counter += 1 
    print 'counter: ', counter 
 
print 'START:', time.time() 
action1 = scheduler.enter(2, 1, increment_counter, ('action1',)) 
action2 = scheduler.enter(3, 1, increment_counter, ('action2',)) 
 
t = threading.Thread(target=scheduler.run) 
t.start() 
scheduler.cancel(action1) 
t.join() 
print 'counter:', counter 
print 'END:', time.time() 


 

    运行结果如下:

    START: 1339666987.27
    action: action2 1339666990.27
    counter:  1
    counter: 1
    END: 1339666990.27

    因为run()函数会引起阻塞,所以我们需要采用线程机制的方法在另一个线程中通过对象的引用取消任务调度,这里只调度了action2方法。

本文出自 “放飞翅膀,追求梦想” 博客,请务必保留此出处http://flykite.blog.51cto.com/4721239/898649

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中有几种方式可以实现任务调度程序。以下是其中几种常见的方法: 1. 使用标准库中的sched模块:sched模块提供了一个简单的任务调度器,可以使用它来安排和执行定时任务。你可以定义一个调度器对象,然后使用其内置的方法来添加和删除任务,并设置任务的执行时间。例如: ```python import sched import time def task(): print("执行任务") scheduler = sched.scheduler(time.time, time.sleep) # 添加任务,延时5秒执行 scheduler.enter(5, 1, task, ()) # 运行调度器 scheduler.run() ``` 2. 使用第三方库APScheduler:APScheduler是一个功能强大的Python任务调度库,它支持多种调度方式,如定时执行、循环执行、延时执行等。你可以使用pip安装APScheduler库,并使用它来创建和管理任务。例如: ```python from apscheduler.schedulers.blocking import BlockingScheduler def task(): print("执行任务") scheduler = BlockingScheduler() # 添加定时任务,每隔5秒执行一次 scheduler.add_job(task, 'interval', seconds=5) # 启动调度器 scheduler.start() ``` 3. 使用Celery:Celery是一个分布式任务队列框架,可以用于异步执行耗时的任务。它支持任务调度、结果存储、负载均衡等功能。你可以使用pip安装Celery库,并设置一个Celery应用程序来定义和调度任务。例如: ```python from celery import Celery app = Celery('task_scheduler', broker='redis://localhost:6379/0') @app.task def task(): print("执行任务") # 添加定时任务,每隔5秒执行一次 app.conf.beat_schedule = { 'task-scheduler': { 'task': 'task_scheduler.task', 'schedule': 5.0, }, } # 启动Celery调度器 app.conf.timezone = 'UTC' app.conf.enable_utc = True app.worker_main(['beat']) ``` 这些方法都可以根据你的需求选择合适的方式来实现任务调度程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值