Python中定时任务框架APScheduler的快速入门指南


Posted in Python onJuly 06, 2017

前言

大家应该都知道在编程语言中,定时任务是常用的一种调度形式,在Python中也涌现了非常多的调度模块,本文将简要介绍APScheduler的基本使用方法。

一、APScheduler介绍

APScheduler是基于Quartz的一个python定时任务框架,实现了Quartz的所有功能,使用起来十分方便。提供了基于日期、固定时间间隔以及crontab类型的任务,并且可以持久化任务。

APScheduler提供了多种不同的调度器,方便开发者根据自己的实际需要进行使用;同时也提供了不同的存储机制,可以方便与Redis,数据库等第三方的外部持久化机制进行协同工作,总之功能非常强大和易用。

在Python的世界中,另外一个齐名的调度模块是Celery,功能也非常的强大,号称分布式的调度器,感兴趣的读者可以自行进行研究。

官网文档地址:http://apscheduler.readthedocs.io/en/latest/

安装包位置: https://pypi.python.org/pypi/APScheduler/

在系统中,如何进行安装呢?其实非常简单,基于pip直接安装即可: 

pip install APScheduler

二、APScheduler的主要的调度类

在APScheduler中有以下几个非常重要的概念,需要大家理解:   

1、触发器(trigger)

包含调度逻辑,每一个作业有它自己的触发器,用于决定接下来哪一个作业会运行,根据trigger中定义的时间点,频率,时间区间等等参数设置。除了他们自己初始配置以外,触发器完全是无状态的。

2、作业存储(job store)

存储被调度的作业,默认的作业存储是简单地把作业保存在内存中,其他的作业存储是将作业保存在数据库中。一个作业的数据讲在保存在持久化作业存储时被序列化,并在加载时被反序列化。调度器不能分享同一个作业存储。job store支持主流的存储机制:redis, mongodb, 关系型数据库, 内存等等

3、执行器(executor)

处理作业的运行,他们通常通过在作业中提交制定的可调用对象到一个线程或者进城池来进行。当作业完成时,执行器将会通知调度器。基于池化的操作,可以针对不同类型的作业任务,更为高效地使用cpu的计算资源。
调度器(scheduler)

通常在应用只有一个调度器,调度器提供了处理这些的合适的接口。配置作业存储和执行器可以在调度器中完成,例如添加、修改和移除作业。

这里简单列一下常用的若干调度器:

  • BlockingScheduler:仅可用在当前你的进程之内,与当前的进行共享计算资源
  • BackgroundScheduler: 在后台运行调度,不影响当前的系统计算运行
  • AsyncIOScheduler: 如果当前系统中使用了async module,则需要使用异步的调度器
  • GeventScheduler: 如果使用了gevent,则需要使用该调度
  • TornadoScheduler: 如果使用了Tornado, 则使用当前的调度器
  • TwistedScheduler:Twister应用的调度器
  • QtScheduler: Qt的调度器

由此可知,在APscheduler的调度器中,是与底层的实现机制紧密相关的,需要依据当前的计算模型来动态选择调度器。

三、APScheduler的job管理

Job是APScheduler中的核心,其承接目前需要执行的工作和任务,其可以在系统运行过程中动态地进行增加/修改/删除/查询等操作。

3.1 Job的新增

共有两种方式进行新增job的操作:

基于add_job来动态增加

代码示例:

sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour='0-9', minute="*", second="*/4")

基于修饰器scheduled_job来动态装饰job的实际函数

代码示例:

@sched.scheduled_job('cron', id='my_job_id', day='last sun') 
def some_decorated_task(): 
 print("I am printed at 00:00:00 on the last Sunday of every month!")

3.2 移除作业

job = scheduler.add_job(myfunc, 'interval', minutes=2) 
job.remove() 
Same, using an explicit job ID: 
 
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id') 
scheduler.remove_job('my_job_id')

基于job id来动态移除特定的job.

3.3 暂停和恢复作业

暂停作业:

  ? apscheduler.job.Job.pause()

  ? apscheduler.schedulers.base.BaseScheduler.pause_job()

恢复作业:

  ? apscheduler.job.Job.resume()

  ? apscheduler.schedulers.base.BaseScheduler.resume_job()

3.4. 获得job列表

获得调度作业的列表,可以使用 get_jobs() 来完成,它会返回所有的job实例。或者使用 print_jobs() 来输出所有格式化的作业列表。

3.5. 修改作业 job

可以通过apscheduler.job.Job.modify() or modify_job()来动态修改job的属性信息,除了job id无法修改之外,都是可以修改的。

job.modify(max_instances=6, name='Alternate name')

另外我们也可以通过apscheduler.job.Job.reschedule() or reschedule_job()动态重新设置trigger,示例如下:

scheduler.reschedule_job('my_job_id', trigger='cron', minute='*/5')

 3.6. 关闭调度器

默认情况下调度器会等待所有正在运行的作业完成后,关闭所有的调度器和作业存储。如果你不想等待,可以将wait选项设置为False。

scheduler.shutdown() 
scheduler.shutdown(wait=False)

四、 APScheduler的代码示例

这里使用装饰器来展示一个调度的使用:

from apscheduler.schedulers.blocking import BlockingScheduler 
 
sched = BlockingScheduler() 
 
@sched.scheduled_job('interval', seconds=3) 
def timed_job(): 
 print('This job is run every three minutes.') 
 
@sched.scheduled_job('cron', day_of_week='mon-fri', hour='0-9', minute='30-59', second='*/3') 
def scheduled_job(): 
 print('This job is run every weekday at 5pm.') 
 
print('before the start funciton') 
sched.start() 
print("let us figure out the situation")

代码说明:

在这段代码中,使用了当前进程中共享计算资源的BlockingScheduler,共使用了2个调度器,其中一个是间隔3秒的执行。

另外一个调度器是模仿cron来执行的,在周一到周五其间,每天的0点到9点直接,在30分到59分之间执行,执行频次为3秒。

基于正常代码的示例如下:

from apscheduler.schedulers.background import BackgroundScheduler 
from apscheduler.schedulers.blocking import BlockingScheduler 
 
import datetime 
import time 
import logging 
 
def job_function(): 
 print "Hello World" + " " + str(datetime.datetime.now()) 
 
if __name__ == '__main__': 
 log = logging.getLogger('apscheduler.executors.default') 
 log.setLevel(logging.INFO) # DEBUG 
 
 fmt = logging.Formatter('%(levelname)s:%(name)s:%(message)s') 
 h = logging.StreamHandler() 
 h.setFormatter(fmt) 
 log.addHandler(h) 
 
 print('start to do it') 
 
 sched = BlockingScheduler() 
 
 # Schedules job_function to be run on the third Friday 
 # of June, July, August, November and December at 00:00, 01:00, 02:00 and 03:00 
 sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour='0-9', minute="*", second="*/4") 
 
 sched.start()

五、某个异常问题的思考

在执行以下代码之时候,定时任务一直未能正常生效:

from apscheduler.schedulers.background import BackgroundScheduler 
from apscheduler.schedulers.blocking import BlockingScheduler 
 
import datetime 
import time 
 
def job_function(): 
 print "Hello World" + " " + str(datetime.datetime.now()) 
 
if __name__ == '__main__': 
 print('start to do it') 
 sched = BlockingScheduler() 
 sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour='0-9', minute="*", second="*/4") 
 sched.start()

代码报错的错误信息为:

No handlers could be found for logger “apscheduler.scheduler”

从字面意思来分析,是没有logging模块的logger存在,故需要添加上去即可。

新增对应的logging信息即可:

import logging
log = logging.getLogger('apscheduler.executors.default') 
 log.setLevel(logging.INFO) # DEBUG 
 
 fmt = logging.Formatter('%(levelname)s:%(name)s:%(message)s') 
 h = logging.StreamHandler() 
 h.setFormatter(fmt) 
 log.addHandler(h)

后来笔者重新做了一次执行,即使移除掉logging的内容,依然可以正常执行,故可以推测为需要动态引入一次依赖包logging即可。

六、总结

APScheduler是一个非常强大易用的类库,为了我们简单快捷的解决问题提供了很多的工具,并且提供了很多灵活的扩展点,只要你添加若干的web页面,就可以创建一个强大的任务调度系统,不是吗?

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python MySQLdb使用教程详解
Mar 20 Python
Python批量合并有合并单元格的Excel文件详解
Apr 05 Python
Python机器学习库scikit-learn安装与基本使用教程
Jun 25 Python
Python IDLE清空窗口的实例
Jun 25 Python
使用Python AIML搭建聊天机器人的方法示例
Jul 09 Python
使用Scrapy爬取动态数据
Oct 21 Python
在pycharm上mongodb配置及可视化设置方法
Nov 30 Python
Python爬虫运用正则表达式的方法和优缺点
Aug 25 Python
python超时重新请求解决方案
Oct 21 Python
flask 实现token机制的示例代码
Nov 07 Python
解决pycharm每次打开项目都需要配置解释器和安装库问题
Feb 26 Python
pip install命令安装扩展库整理
Mar 02 Python
Python如何快速实现分布式任务
Jul 06 #Python
Python3下错误AttributeError: ‘dict’ object has no attribute’iteritems‘的分析与解决
Jul 06 #Python
Python标准库sched模块使用指南
Jul 06 #Python
用virtualenv建立多个Python独立虚拟开发环境
Jul 06 #Python
基于Python的关键字监控及告警
Jul 06 #Python
Python中装饰器兼容加括号和不加括号的写法详解
Jul 05 #Python
利用python模拟sql语句对员工表格进行增删改查
Jul 05 #Python
You might like
用PHP实现维护文件代码
2007/06/14 PHP
Laravel 5框架学习之Eloquent (laravel 的ORM)
2015/04/08 PHP
jQuery向下滚动即时加载内容实现的瀑布流效果
2016/01/07 PHP
php连接mysql数据库
2017/03/21 PHP
PHP微信发送推送消息乱码的解决方法
2019/02/28 PHP
ThinkPHP3.2.3框架Memcache缓存使用方法实例总结
2019/04/15 PHP
javascript web页面刷新的方法收集
2009/07/02 Javascript
28个JS验证函数收集
2010/03/02 Javascript
使用Post提交时须将空格转换成加号的解释
2013/01/14 Javascript
jQuery Mobile的loading对话框显示/隐藏方法分享
2013/11/26 Javascript
JS中attr和prop属性的区别以及优先选择示例介绍
2014/06/30 Javascript
jQuery源码分析之jQuery.fn.each与jQuery.each用法
2015/01/23 Javascript
JavaScript从0开始构思表情插件
2016/07/26 Javascript
jQuery可见性过滤选择器用法示例
2016/09/09 Javascript
Angular开发者指南之入门介绍
2017/03/05 Javascript
JavaScript 中 apply 、call 的详解
2017/03/21 Javascript
VueJs使用Amaze ui调整列表和内容页面
2017/11/30 Javascript
基于javascript 显式转换与隐式转换(详解)
2017/12/15 Javascript
JS实现的汉字与Unicode码相互转化功能分析
2018/05/25 Javascript
深入浅出理解JavaScript闭包的功能与用法
2018/08/01 Javascript
深入浅析var,let,const的异同点
2018/08/07 Javascript
解决vue中使用proxy配置不同端口和ip接口问题
2019/08/14 Javascript
JavaScript中的各种宽高属性的实现
2020/05/08 Javascript
Apache如何部署django项目
2017/05/21 Python
Python设计模式之备忘录模式原理与用法详解
2019/01/15 Python
简单了解python gevent 协程使用及作用
2019/07/22 Python
解决Python中回文数和质数的问题
2019/11/24 Python
pip/anaconda修改镜像源,加快python模块安装速度的操作
2021/03/04 Python
一款利用html5和css3实现的3D滚动特效的教程
2015/01/04 HTML / CSS
法学专业应届生求职信
2013/10/16 职场文书
专科应届生求职信
2013/11/24 职场文书
个人公开承诺书
2014/03/28 职场文书
大专生自我鉴定怎么写
2014/09/16 职场文书
通知函格式范文
2015/04/27 职场文书
Python虚拟环境virtualenv是如何使用的
2021/06/20 Python
SpringBoot深入分析讲解监听器模式下
2022/07/15 Java/Android