定时任务工具apscheduler
APScheduler简介
Apscheduler基于Quartz的一个python定时任务框架,实现Quart的所有功能,目前其提供了基于日期、固定时间间隔以及corntab类型的任务,并且同时可进行持久化任务;同时它提供了多种不同的调用器,方便开发者根据自己的需求进行使用,也方便与数据库等第三方的外部持久化储存机制进行协同工作。
官方文档:传送门
基本原理
总的来说,主要是利用python threading Event和Lock锁来写的。scheduler在主循环(main_loop)中, 反复检查是否有需要执行的任务,完成任务的检查函数为 _process_jobs,主要有那个几个步骤:
1、 询问储存的每个 jobStore,是否有到期要执行的任务。
due_jobs=jobstore.get_due_jobs(now)
2、 due_jobs 不为空,则计算这些jobs中每个job需要运行的时间点,时间一到就提交给submit作任务调度。
run_times = job._get_run_times(now)
...
if run_times:
try:
executor.submit_job(job, run_times)
3、在主循环中,如果不间断地调用,而实际上没有要执行的job,这会造成资源浪费。因此在程序中,如果每次掉用 _process_jobs 后,进行了预先判断,判断下一次要执行的job(离现在最近的)还要多长时间,作为返回值告诉main_loop, 这时主循环就可以去睡一觉,等大约这么长时间后再唤醒,执行下一次 _process_jobs 。
详情参见:apscheduler/scheduler/base.py中_process_jobs函数
组成
APScheduler 由以下四部分组成:
- triggers(触发器):
指定定时任务执行的时机。有data 、 interval 、 cron 三种类别。 - job stores(存储器) :
可以将定时持久存储。作业存储支持主流的存储机制:如redis,mongodb,关系型数据库,内存等等,默认存储在内存中。 - executors(执行器):
在定时任务该执行时,以进程或线程方式执行任务 - schedulers(调度器):
常用的有BackgroundScheduler(后台运行)和BlockingScheduler(阻塞式)
示例
代码:
#coding=utf-8
from flask import Flask
from flask_apscheduler import APScheduler
from apscheduler.jobstores.redis import RedisJobStore
from flask import request
import os
import time
app = Flask(__name__)
scheduler = APScheduler()
class Config(object):
JOBS = []
SCHEDULER_JOBSTORES = {
'default': RedisJobStore(host = "Your redis host", port = 6379, db = 0, password = 'Your redis password')
}
SCHEDULER_EXECUTORS = {
'default': {'type': 'threadpool', 'max_workers': 20}
}
SCHEDULER_JOB_DEFAULTS = {
'coalesce': False,
'max_instances': 3
}
SCHEDULER_API_ENABLED = True
def job1(a, b):
print(str(a) + ' ' + str(b)+' '+time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
def job2(a):
py='python wx_post_test.py '+a
os.system(py)
def jobfromparm(**jobargs):
id = jobargs['id']
job = scheduler.add_job(func=job1,id=id, args=(1,2),trigger='interval',seconds=10,replace_existing=True) # interval间隔调度,即每隔多久执行一次
#job = scheduler.add_job(func = job1, id = id, args = (1,2), trigger = 'cron', day_of_week = '0-6', hour = '20', minute = '14',replace_existing=True) # corn 定时调度,即规定在某一时刻执行
#job = scheduler.add_job(func = job1, id = id, args = (1, 2), trigger = 'date', run_date = '2019-11-26 16:30:05',replace_existing=True) # data定时调度,即设置后作业只会执行一次,是最基本的调度模式
return 'sucess'
@app.route('/pause')
def pausejob():
job_id = request.args.get('job_id')
scheduler.pause_job(job_id)
return "Success!"
@app.route('/resume')
def resumejob():
scheduler.resume_job('job1')
return "Success!"
@app.route('/addjob', methods=['GET', 'POST'])
def addjob():
data = request.get_json(force=True)
print(data)
job = jobfromparm(**data)
return 'sucess'
@app.route('/getjobs', methods=['GET', 'POST'])
def getjobs():
jobs = scheduler.get_jobs()
return str(jobs)
@app.route('/delete')
def deletejob():
job_id = request.args.get('job_id')
scheduler.remove_job(job_id)
return "Success!"
if __name__ == '__main__':
#app = Flask(__name__)
app.config.from_object(Config())
# it is also possible to enable the API directly
# scheduler.api_enabled = True
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
app.run(debug=True)
运行:
curl -i -X POST -H "'Content-type':'appon/x-www-form-urlencoded', 'charset':'utf-8', 'Accept': 'text/plain'" -d '{"id":"1"}' http://127.0.0.1:5000/addjob
结果: