Python定时任务

介绍python中实现定时任务的几种方式。

Timer

Timerthreading提供的一个阻塞函数,用于延迟执行任务。

为了利用Timer实现定时任务,需要使用一个递归来实现,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
from datetime import datetime
from threading import Timer

i = 0

def ding(period):
global i
print i, datetime.now().strftime("%Y-%m-%d %H:%M:%S")
i += 1
t = Timer(period, ding, (period,))
t.start()

ding(3)

sched

schedPython内置的一个调度模块(详情)。

创建调度任务:

1
2
sched.scheduler(timefunc, delayfunc)
# timefunc, delayfunc延迟等待指定的函数

sched使用调度队列来管理调度任务,

1
2
3
4
5
6
7
8
9
10
11
# 调度任务队列,用来存储未执行的任务
scheduler.queue
# 调度任务队列是否为空
scheduler.empty()
# 执行调度任务
scheduler.run()
# 增加任务,向任务队列中增加任务
# delay延迟时间/priority优先级/action执行函数/argument函数参数
scheduler.enter(delay, priority, action, argument)
# 取消任务,从任务队列中删除任务
scheduler.cancel(event)

实例,需要注意如果使用delayfunc中包含延时功能,当延时时间大于任务延时时间)可能会增大延时时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import time
import sched
from datetime import datetime

schedule = sched.scheduler(time.time, time.sleep)

i = 0

def ding(period):
global i
print i, datetime.now().strftime("%Y-%m-%d %H:%M:%S")
schedule.enter(period, 0, ding, (period,))
i += 1

def main(period=3):
schedule.enter(0, 0, ding, (period,))
schedule.run()

main()

apscheduler

apscheduler是一个Python定时任务框架,全称Advanced Python Scheduler文档)。

组件

triggers是用于启动调度逻辑的触发器,每一个任务都拥有自己的触发器。

1
特定日期`date`、固定间隔`interval`、特定时间定时`cron`

job stores是用来存储调度任务,可选内存、缓存、数据库作为存储媒介。

1
2
3
MemoryJobStore内存存储(默认)
MongoDBJobStore数据库存储
SQLAlchemyJobStore数据库存储

executors是用来执行调度任务的,可使用线程或进程池作为执行器。

1
2
ThreadPoolExecutor线程池执行器(默认)
ProcessPoolExecutor进程池执行器

scheduler主要是用于选择阻塞、异步模型,提供了geventTornador等框架的支持。

1
2
3
4
5
6
7
BlockingScheduler:阻塞式;
BackgroundScheduler:用于后台执行(需要保证主线程运行,否则关闭);
AsyncIOScheduler:用于异步IO;
GeventScheduler: 用于gevent;
TornadoScheduler: 用于Tornador;
TwistedScheduler: 用于Twisted;
QtScheduler: 用于Qt;

举例

例1中选择了阻塞调度器BlockingScheduler,并通过设置间隔执行interval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 例1
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

i = 0

def ding():
global i
print i, datetime.now().strftime("%Y-%m-%d %H:%M:%S")
i += 1

scheduler = BlockingScheduler()
scheduler.add_job(ding, 'interval', seconds=3)
scheduler.start()

例12中选择了后台调度器BackgroundScheduler,增加两个任务分别使用intervalcron来设置触发器,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 例2
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime

i = 0

def ding(name):
global i
print i, name, datetime.now().strftime("%Y-%m-%d %H:%M:%S")
i += 1

scheduler = BackgroundScheduler()
scheduler.add_job(ding, 'interval', seconds=3, args=('interval',))
scheduler.add_job(ding, 'cron', second='*/1', args=('cron',))
scheduler.start()
print 'background scheduler start ... sleep'
import time
time.sleep(10)

更多复杂的例子…