APScheduler - Advanced Python Scheduler
简介
APScheduler:强大的任务调度工具,可以完成定时任务,周期任务等,它是跨平台的,用于取代Linux下的cron daemon或者Windows下的task scheduler。
内置三种调度调度系统:
- Cron风格
- 间隔性执行
- 仅在某个时间执行一次
作业存储的backends支持:
- Memory
- SQLAlchemy (any RDBMS supported by SQLAlchemy works)
- MongoDB
- Redis
- RethinkDB
- ZooKeeper
基本概念:4个组件
triggers: 描述一个任务何时被触发,有按日期、按时间间隔、按cronjob描述式三种触发方式
job stores: 任务持久化仓库,默认保存任务在内存中,也可将任务保存都各种数据库中,任务中的数据序列化后保存到持久化数据库,从数据库加载后又反序列化。
executors: 执行任务模块,当任务完成时executors通知schedulers,schedulers收到后会发出一个适当的事件
schedulers: 任务调度器,控制器角色,通过它配置job stores和executors,添加、修改和删除任务。
插件机制: 供用户自由选择scheduler, job store(s), executor(s) and trigger(s)
scheduler
scheduler的主循环(main_loop),其实就是反复检查是不是有到时需要执行的任务,完成一次检查的函数是_process_jobs, 这个函数做这么几件事:
- 询问自己的每一个jobstore,有没有到期需要执行的任务(jobstore.get_due_jobs())
- 如果有,计算这些job中每个job需要运行的时间点(run_times = job._get_run_times(now))如果run_times有多个,这种情况我们上面讨论过,有coalesce检查
提交给executor排期运行(executor.submit_job(job, run_times)) - 那么在这个_process_jobs的逻辑,什么时候调用合适呢?如果不间断地调用,而实际上没有要执行的job,是一种浪费。每次掉用_process_jobs后,其实可以预先判断一下,下一次要执行的job(离现在最近的)还要多长时间,作为返回值告诉main_loop, 这时主循环就可以去睡一觉,等大约这么长时间后再唤醒,执行下一次_process_jobs。这里唤醒的机制就会有IO模型的区别了
scheduler由于IO模型的不同,可以有多种实现,内置scheduler供选:
BlockingScheduler: scheduler在当前进程的主线程中运行,所以调用start函数会阻塞当前线程,不能立即返回。BackgroundScheduler: 放到后台线程中运行,所以调用start后主线程不会阻塞AsyncIOScheduler: 使用asyncio模块GeventScheduler: 使用gevent作为IO模型,和GeventExecutor配合使用TornadoScheduler: 配合TwistedExecutor,用reactor.callLater完成定时唤醒TwistedScheduler: 使用tornado的IO模型,用ioloop.add_timeout完成定时唤醒QtScheduler: 使用QTimer完成定时唤醒
jobstore
jobstore提供给scheduler一个序列化jobs的统一抽象,提供对scheduler中job的增删改查接口,根据存储backend的不同,分以下几种
内置job stores供选:
MemoryJobStore:没有序列化,jobs就存在内存里,增删改查也都是在内存中操作SQLAlchemyJobStore:所有sqlalchemy支持的数据库都可以做为backend,增删改查操作转化为对应backend的sql语句MongoDBJobStore:用mongodb作backendRedisJobStore: 用redis作backend
除了MemoryJobStore外,其他几种都使用pickle做序列化工具,所以这里要指出一点,如果你不是在用内存做jobstore,那么必须确保你提供给job的可执行函数必须是可以被全局访问的,也就是可以通过ref_to_obj反查出来的,否则无法序列化。
使用数据库做jobstore,就会发现,其实创建了一张有三个域的的jobs表,分别是****id, next_run_time, job_state,其中job_state是job对象pickle序列化后的二进制**,而id和next_run_time则是支持job的两类查询(按id和按最近运行时间)
executor
aps把任务最终的执行机制也抽象了出来,可以根据IO模型选配,不需要讲太多,最常用的是threadpool和processpoll两种(来自concurrent.futures的线程/进程池)。
不同类型的executor实现自己的_do_submit_job,完成一次实际的任务实例执行。以线程/进程池实现为例
内置executors供选:
ProcessPoolExecutor: 多进程,可指定进程数,当工作负载为CPU密集型操作时可以考虑使用它来利用多核CPUThreadPoolExecutor: 多线程,可指定线程数,默认,可以满足大多数用途AsyncIOExecutorDebugExecutorGeventExecutorProcessPoolExecutorThreadPoolExecutorTwistedExecutor
trigger
trigger是抽象出了“一个job是何时被触发”这个策略,每种trigger实现自己的get_next_fire_time函数
aps提供的trigger包括:
date:一次性指定日期interval:在某个时间范围内间隔多长时间执行一次cron:和unix crontab格式兼容,最为强大
默认配置: 使用MemoryJobStore和ThreadPoolExecutor
优点:插件化思想和抽象出接口,策略与不同实现机制分离
User guide
配置scheduler
官网提供了等价的三种方法,第一种比较简洁明了。
from pytz import utc
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
jobstores = {
'mongo': MongoDBJobStore(),
'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
executors = {
'default': ThreadPoolExecutor(20),
'processpool': ProcessPoolExecutor(5)
}
job_defaults = {
'coalesce': False,
'max_instances': 3
}
scheduler = BackgroundScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
from apscheduler.schedulers.background import BackgroundScheduler
# 使用默认配置,即MemoryJobStore和ThreadPoolExecutor(10)
scheduler = BackgroundScheduler()
启动调度器
调用调度器的start()方法
添加任务
两种方式:
- 调用调度器的
add_job() - 使用调度器的
scheduled_job()装饰器: 很简洁,推荐这种。
其他的不常用操作如移除任务、暂停和恢复任务、获取调度了的任务列表、修改任务、关停调度器、暂停/恢复任务处理等见文档:http://apscheduler.readthedocs.io/en/latest/userguide.html
限制并发执行的任务实例数量
默认同一时刻只能有一个实例运行,通过max_instances=3修改为3个。
错过执行的任务与合并
misfire_grace_time:如果一个job本来14:00有一次执行,但是由于某种原因没有被调度上,现在14:01了,这个14:00的运行实例被提交时,会检查它预订运行的时间和当下时间的差值(这里是1分钟),大于我们设置的30秒限制,那么这个运行实例不会被执行。
合并:最常见的情形是scheduler被shutdown后重启,某个任务会积攒了好几次没执行如5次,下次这个job被submit给executor时,执行5次。将coalesce=True后,只会执行一次
Scheduler 事件
监听Scheduler发出的事件并作出处理,如任务执行完、任务出错等
def my_listener(event):
if event.exception:
print('The job crashed :(') # or logger.fatal('The job crashed :(')
else:
print('The job worked :)')
scheduler.add_listener(my_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
APScheduler - Advanced Python Scheduler的更多相关文章
- APScheduler(Python化的Cron)使用总结 定时任务
APScheduler(Python化的Cron)使用总结 简介 APScheduler全程为Advanced Python Scheduler,是一款轻量级的Python任务调度框架.它允许你像Cr ...
- apscheduler 设置python脚本定时任务
理论概念:https://zhuanlan.zhihu.com/p/95563033 BlockingScheduler与BackgroundScheduler区别 :https://www.jian ...
- 用apscheduler写python定时脚本
apscheduler 官方文档:http://apscheduler.readthedocs.io/en/latest/ 写一个后台定时任务,一般2个选择,一个是apscheduler,一个cele ...
- [Advanced Python] 10 - Transfer parameters
动态库调用 一.Python调用 .so From: Python调用Linux下的动态库(.so) (1) 生成.so:.c to .so lolo@-id:workme$ gcc -Wall -g ...
- [Advanced Python] 11 - Implement a Class
基础概念:[Python] 08 - Classes --> Objects 进阶概念:[Advanced Python] 11 - Implement a Class 参考资源:廖雪峰,面向对 ...
- [Advanced Python] 16 - Google style guide for programming
Ref: Python 风格指南 - 内容目录 这里主要记录一下值得注意的地方. Python语言规范 Lint:vsCode自带 导入:完整路径 异常 Ref: [Python] 07 - Stat ...
- [Advanced Python] 14 - "Generator": calculating prime
高性能编程 几个核心问题 • 生成器是怎样节约内存的?• 使用生成器的最佳时机是什么?• 我如何使用 itertools 来创建复杂的生成器工作流?• 延迟估值何时有益,何时无益? From: htt ...
- [Advanced Python] 15 - "Metaclass": ORM
From: 使用元类 动态创建类 与静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 一 .type()动态创建 我们说class的定义是运行时动态创建的: 而创建cl ...
- [Advanced Python] 12 - Interview Quiz
第一步.大扫荡复习 Resource: https://www.liaoxuefeng.com/wiki/1016959663602400/1016959735620448 IDE:https://r ...
随机推荐
- esLint参数设置
package.json { "name": "testEsLint", "version": "1.0.0", &qu ...
- LSB含义
LSB(Least Significant Bit)最低有效位,对任何AD来说,量化后输出的数字信号值都是以1LSB的电压值步进的,介于1LSB之间的电压将按照一定的规则进行入位或舍弃,这个过程中造成 ...
- [UI基础][实现]九宫格之应用程序管理
[目标] 1.完成下图所示的View,View中的图片.文字数据从app.list文件读出. 2.思考代码哪里可以进行优化. [分析] 1.创建控件 整个View分12个部分,其中包含一个 UIIma ...
- 利用Minhash和LSH寻找相似的集合(转)
问题背景 给出N个集合,找到相似的集合对,如何实现呢?直观的方法是比较任意两个集合.那么可以十分精确的找到每一对相似的集合,但是时间复杂度是O(n2).当N比较小时,比如K级,此算法可以在接受的时间范 ...
- 雷林鹏分享:Ruby 面向对象
Ruby 面向对象 Ruby 是纯面向对象的语言,Ruby 中的一切都是以对象的形式出现.Ruby 中的每个值都是一个对象,即使是最原始的东西:字符串.数字,甚至连 true 和 false 都是对象 ...
- 获取iframe(angular 动态页面)高度
问题比较特殊,google了好久才得到启示 开发的angular页面,需要嵌入到客户的web页中,以iframe方式.由于iframe的高度需要指定,而angular动态生成机制导致页面高度会随时变化 ...
- PowerDesigner16工具学习笔记-建立BPM
根据不同用途,BPM分为分析性(Analysis).执行型(Executable)和协作型(Collaborative) BPM的类型 业务流程语言 描述 分析型 Analysis 提供流程层次 ...
- HDU-1794 方格填数 (贪心+四分)
题目大意:给一个由自然数构成的nxn方阵,其中有k个元素为0,现在要从给出的m个元素中挑出k个填入矩阵,是和的增量最大.和定义为所有子方阵上的元素之和. 题目分析:对于尺寸固定的方阵,计算和的时候每个 ...
- Spring Boot 整合Swagger2构建API文档
1.pom.xml中引入依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>spri ...
- wikioi 1028 花店橱窗布置 最大权匹配
中文题意不描述. 链接:http://wikioi.com/problem/1028/ 这题一开始很裸的最大权二分匹配.但是原来没有接触过,KM的这个最大权不大会.然后一开始以为用最大费用最大流直接就 ...