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插入排序算法实例分析
Jul 03 Python
儿童学习python的一些小技巧
May 27 Python
python筛选出两个文件中重复行的方法
May 31 Python
numpy中矩阵合并的实例
Jun 15 Python
修改默认的pip版本为对应python2.7的方法
Nov 06 Python
python3格式化字符串 f-string的高级用法(推荐)
Mar 04 Python
Python实现的北京积分落户数据分析示例
Mar 27 Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
May 15 Python
在Python中字典按值排序的实现方法
Nov 12 Python
python录音并调用百度语音识别接口的示例
Dec 01 Python
Python 机器学习工具包SKlearn的安装与使用
May 14 Python
使用Python拟合函数曲线
Apr 14 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面向对象五大原则之单一职责原则(SRP)详解
2018/04/04 PHP
PHP实现数据四舍五入的方法小结【4种方法】
2019/03/27 PHP
Laravel5.5 实现后台管理登录的方法(自定义用户表登录)
2019/09/30 PHP
ExtJS 工具栏 分页事件参数
2010/03/05 Javascript
父子窗体间传递JSON格式的数据的代码
2010/12/25 Javascript
表单元素的submit()方法和onsubmit事件应用概述
2013/02/01 Javascript
使用Plupload实现直接上传附件至七牛云存储
2014/12/26 Javascript
JavaScript操作cookie类实例
2015/03/31 Javascript
jquery中$each()方法的使用指南
2015/04/30 Javascript
javascript获取select标签选中的值
2016/06/04 Javascript
使用JS批量选中功能实现更改数据库中的status状态值(批量展示)
2016/11/22 Javascript
assert()函数用法总结(推荐)
2017/01/25 Javascript
JS日程管理插件FullCalendar中文说明文档
2017/02/06 Javascript
vue实现一个移动端屏蔽滑动的遮罩层实例
2017/06/08 Javascript
浅谈Vue.js应用的四种AJAX请求数据模式
2017/08/30 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
详解Python进程间通信之命名管道
2017/08/28 Python
python 接口测试response返回数据对比的方法
2018/02/11 Python
python 实时得到cpu和内存的使用情况方法
2018/06/11 Python
pip安装时ReadTimeoutError的解决方法
2018/06/12 Python
pycharm 在windows上编辑代码用linux执行配置的方法
2018/10/27 Python
Python2和Python3.6环境解决共存问题
2018/11/09 Python
Python中一个for循环循环多个变量的示例
2019/07/16 Python
python双向链表原理与实现方法详解
2019/12/03 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
2020/06/08 Python
哪种Python框架适合你?简单介绍几种主流Python框架
2020/08/04 Python
外企C语言笔试题
2013/11/10 面试题
linux面试题参考答案(8)
2016/04/19 面试题
UNIX特点都有哪些
2016/04/05 面试题
教学大赛获奖感言
2014/01/15 职场文书
师生聚会感言
2014/01/26 职场文书
致跳远运动员广播稿
2014/02/11 职场文书
秋天的怀念教学反思
2014/04/28 职场文书
大学军训的体会
2014/11/08 职场文书
css3实现背景图片颜色修改的多种方式
2021/04/13 HTML / CSS
基于tensorflow权重文件的解读
2021/05/26 Python