APScheduler是一个python库,用于进程内任务调度。我们可以用它调度python代码,使被调度的python代码在将来某个时刻或某些时刻执行。并且,我们可以随心所欲的增加或删除任务。如果将任务存在数据库中,那么这些任务在调度器重启后仍然有效,并保持着之前的状态。当调度程序重启后,调度器将运行那些因为调度器不在而没能执行的任务。除此之外,APScheduler可以用作一个跨平台的调度器,比如cron守护进程,windows任务调度器。但请注意,APScheduler不是守护进程,它也不是服务,并且它也没有任何命令行工具,它只是运行在已经运行的进程中。这就是说,APScheduler只是提供一些模块,用于构建一个调度服务或者专用调度程序。
APScheduler组成部分:
triggers
job stores
executors
schedulers
triggers: triggers包含调度逻辑。每个job都有它自己的trigger,这个trigger决定了该job下一次运行在什么时间。Trigger是无状态的,它只有保持有初始化时的配置:
Cron式调度(和crontab一样)
Interval方式调度(间隔执行)
date方式调度(指定时间执行一次)
if jobtype == 'interval':
job = self.scheduler.add_job(method, 'interval', seconds=trigger,
id=jobid, args=args, kwargs=kwargs)
if jobtype == 'cron':
Trigger = CronTrigger(**trigger)
job = self.scheduler.add_job(method, Trigger,
id=jobid, args=args, kwargs=kwargs)
if jobtype == 'once':
job = self.scheduler.add_job(method, 'date', run_date=trigger,
id=jobid, args=args, kwargs=kwargs)
job stores:Job stores保存有job的调度计划。默认的job stores是内存,但是,也可以保存到各种数据库中。Job保存时将其序列化,读取时再将其反序列化。Job stores不能被多个schedulers共享。支持存储后端:内存、SQLAlchemy(RDBMS支持通过各自的作品)、MongoDB、redis。
executors:Executors用于处理运行中的job。通常只是将job提交到一个可用的线程池/进程池。当job完成后,executor通知scheduler。
schedulers:Schedulers是调度器,通常在一个应用程序中只有一个scheduler运行。应用程序开发人员通常不直接处理job stores, executors或triggers,而是使用scheduler提供的接口去处理。配置job stores, executors都是通过scheduler完成的,比如添加、修改、移除job。
完整代码:
# -*- coding:UTF-8-*-
__author__ = 'Aaron'
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from oslo_log import log
from datetime import datetime
import time
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
from apscheduler.events import *
#EVENT_JOB_ADDED = 128
#EVENT_JOB_REMOVED = 256
#EVENT_JOB_MODIFIED = 512
#EVENT_JOB_EXECUTED = 1024
#EVENT_JOB_ERROR = 2048
#EVENT_JOB_MISSED = 4096#
LISTENER_JOB = (EVENT_JOB_ADDED |
EVENT_JOB_REMOVED |
EVENT_JOB_MODIFIED |
EVENT_JOB_EXECUTED |
EVENT_JOB_ERROR |
EVENT_JOB_MISSED)
JOB_DEFAULTS = {
'misfire_grace_time': 1,
'coalesce': False,
'max_instances': 100
}
EXECUTORS = {
'default': ThreadPoolExecutor(1),
'processpool': ProcessPoolExecutor(4)
}
def method(job_id):
print('Job ' + str(job_id) + ' begin! The time is: %s' % datetime.now())
time.sleep(2)
print('Job ' + str(job_id) + ' end! The time is: %s' % datetime.now())
def err_listener(events):
if events.code == EVENT_JOB_MISSED:
print "Job %s has missed." % str(events.job_id)
class JobManager(object):
def __init__(self):
self.scheduler = BackgroundScheduler(executors=EXECUTORS, job_defaults=JOB_DEFAULTS, timezone='Asia/Shanghai')
self.jobs = {}
self.scheduler.add_listener(err_listener, LISTENER_JOB)
self.scheduler.start()
print datetime.now()
def add_job(self, jobid):
trigger = dict(hour=17, minute=52)
Trigger = CronTrigger(**trigger)
job = self.scheduler.add_job(method, Trigger, id=jobid, args=[jobid])
print "add job %s successful!" % jobid + "; next_run_time: " + str(job.next_run_time)
if __name__ == "__main__":
a = JobManager()
for i in range(1, 3):
a.add_job('%d' % i)
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
a.scheduler.shutdown()