前言

APScheduler是python下的任务调度框架,全程为Advanced Python Scheduler,是一款轻量级的Python任务调度框架。它允许你像Linux下的Crontab那样安排定期执行的任务,并且支持Python函数或任意可调用的对象。

安装

(ENV1) [eason@localhost]$ pip install apscheduler
Collecting apscheduler
Downloading APScheduler-3.3.0-py2.py3-none-any.whl (57kB)
100% |████████████████████████████████| 61kB 81kB/s
Collecting pytz (from apscheduler)
Downloading pytz-2016.10-py2.py3-none-any.whl (483kB)
100% |████████████████████████████████| 491kB 52kB/s
Collecting funcsigs; python_version == "2.7" (from apscheduler)
Downloading funcsigs-1.0.2-py2.py3-none-any.whl
Requirement already satisfied: six>=1.4.0 in /home/eason/ENV1/lib/python2.7/site-packages (from apscheduler)
Collecting tzlocal>=1.2 (from apscheduler)
Downloading tzlocal-1.3.tar.gz
Requirement already satisfied: setuptools>=0.7 in /home/eason/ENV1/lib/python2.7/site-packages (from apscheduler)
Collecting futures; python_version == "2.7" (from apscheduler)
Downloading futures-3.0.5-py2-none-any.whl
Building wheels for collected packages: tzlocal
Running setup.py bdist_wheel for tzlocal ... done
Stored in directory: /home/eason/.cache/pip/wheels/80/19/a8/635ad9f4ad8a63b49d073c55cbca31fb5898ce2560ed145a69
Successfully built tzlocal
Installing collected packages: pytz, funcsigs, tzlocal, futures, apscheduler
Successfully installed apscheduler-3.3.0 funcsigs-1.0.2 futures-3.0.5 pytz-2016.10 tzlocal-1.3
(ENV1) [eason@localhost]$

基本概念

APScheduler 有四种组件:

  • triggers
  • job stores
  • executors
  • schedulers

triggers(触发器)中包含调度逻辑,每个作业都由自己的触发器来决定下次运行时间。除了他们自己初始配置意外,触发器完全是无状态的。

job stores(作业存储器)存储被调度的作业,默认的作业存储器只是简单地把作业保存在内存中,其他的作业存储器则是将作业保存在数据库中。当作业被保存到一个持久化的作业存储器中的时候,该作业的数据会被序列化,并在加载时被反序列化。作业存储器不能共享调度器。

executors(执行器)处理作业的运行,他们通常通过在作业中提交指定的可调用对象到一个线程或者进城池来进行。当作业完成时,执行器将会通知调度器。

schedulers(调度器)配置作业存储器和执行器可以在调度器中完成,例如添加、修改和移除作业。根据不同的应用场景可以选用不同的调度器,可选的有BlockingScheduler,BackgroundScheduler,AsyncIOScheduler,GeventScheduler,TornadoScheduler,TwistedScheduler,QtScheduler 7种。

选择合适的调度器

  • BlockingScheduler : 当调度器是你应用中唯一要运行的东西时
  • BackgroundScheduler : 当你没有运行任何其他框架并希望调度器在你应用的后台执行时使用。
  • AsyncIOScheduler : 当你的程序使用了asyncio(一个异步框架)的时候使用。
  • GeventScheduler : 当你的程序使用了gevent(高性能的Python并发框架)的时候使用。
  • TornadoScheduler : 当你的程序基于Tornado(一个web框架)的时候使用。
  • TwistedScheduler : 当你的程序使用了Twisted(一个异步框架)的时候使用
  • QtScheduler : 如果你的应用是一个Qt应用的时候可以使用。

选择合适的作业存储器

如果你的应用在每次启动的时候都会重新创建作业,那么使用默认的作业存储器(MemoryJobStore)即可,但是如果你需要在调度器重启或者应用程序奔溃的情况下任然保留作业,你应该根据你的应用环境来选择具体的作业存储器。例如:使用Mongo或者SQLAlchemy JobStore (用于支持大多数RDBMS)

关于执行器

对执行器的选择取决于你使用上面哪些框架,大多数情况下,使用默认的ThreadPoolExecutor已经能够满足需求。如果你的应用涉及到CPU密集型操作,你可以考虑使用ProcessPoolExecutor来使用更多的CPU核心。你也可以同时使用两者,将ProcessPoolExecutor作为第二执行器。

关于触发器

当你调度作业的时候,你需要为这个作业选择一个触发器,用来描述这个作业何时被触发,APScheduler有三种内置的触发器类型:

  • date 一次性指定日期
  • interval 在某个时间范围内间隔多长时间执行一次
  • cron 和Linux crontab格式兼容,最为强大

date 最基本的一种调度,作业只会执行一次。它的参数如下:

  1. run_date (datetime|str) – 作业的运行日期或时间
  2. timezone (datetime.tzinfo|str) – 指定时区

举个栗子:

# 2016-12-12运行一次job_function
sched.add_job(job_function, 'date', run_date=date(2016, 12, 12), args=['text'])
# 2016-12-12 12:00:00运行一次job_function
sched.add_job(job_function, 'date', run_date=datetime(2016, 12, 12, 12, 0, 0), args=['text'])

interval 间隔调度,参数如下:

  1. weeks (int) – 间隔几周
  2. days (int) – 间隔几天
  3. hours (int) – 间隔几小时
  4. minutes (int) – 间隔几分钟
  5. seconds (int) – 间隔多少秒
  6. start_date (datetime|str) – 开始日期
  7. end_date (datetime|str) – 结束日期
  8. timezone (datetime.tzinfo|str) – 时区

举个栗子:

# 每两个小时调一下job_function
sched.add_job(job_function, 'interval', hours=2)

cron参数如下:

  1. year (int|str) – 年,4位数字
  2. month (int|str) – 月 (范围1-12)
  3. day (int|str) – 日 (范围1-31)
  4. week (int|str) – 周 (范围1-53)
  5. day_of_week (int|str) – 周内第几天或者星期几 (范围0-6 或者 mon,tue,wed,thu,fri,sat,sun)
  6. hour (int|str) – 时 (范围0-23)
  7. minute (int|str) – 分 (范围0-59)
  8. second (int|str) – 秒 (范围0-59)
  9. start_date (datetime|str) – 最早开始日期(包含)
  10. end_date (datetime|str) – 最晚结束时间(包含)
  11. timezone (datetime.tzinfo|str) – 指定时区

取值格式:

表达式 参数 描述
* any Fire on every value
*/a any Fire every a values, starting from the minimum
a-b any Fire on any value within the a-b range (a must be smaller than b)
a-b/c any Fire every c values within the a-b range
xth y day Fire on the x -th occurrence of weekday y within the month
last x day Fire on the last occurrence of weekday x within the month
last day Fire on the last day within the month
x,y,z any Fire on any matching expression; can combine any number of any of the above expressions

举个栗子:

# job_function将会在6,7,8,11,12月的第3个周五的1,2,3点运行
sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
# 截止到2016-12-30 00:00:00,每周一到周五早上五点半运行job_function
sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2016-12-31')

实践

添加作业有两种方法,一种是使用add_job()函数,还有一种方式是通过scheduled_job()装饰器。

add_job()函数方式

from apscheduler.schedulers.blocking import BlockingScheduler
import datetime def my_job1():
print 'my_job1 is running, Now is %s' % datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") def my_job2():
print 'my_job2 is running, Now is %s' % datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") sched = BlockingScheduler()
# 每隔5秒运行一次my_job1
sched.add_job(my_job1, 'interval', seconds=5,id='my_job1')
# 每隔5秒运行一次my_job2
sched.add_job(my_job2,'cron',second='*/5',id='my_job2')
sched.start()

执行结果:

$my_job2 is running, Now is 2016-12-13 14:41:10
$my_job1 is running, Now is 2016-12-13 14:41:12
$my_job2 is running, Now is 2016-12-13 14:41:15
$my_job1 is running, Now is 2016-12-13 14:41:17
$my_job2 is running, Now is 2016-12-13 14:41:20
$my_job1 is running, Now is 2016-12-13 14:41:22
$my_job2 is running, Now is 2016-12-13 14:41:25
$my_job1 is running, Now is 2016-12-13 14:41:27

scheduled_job()装饰器方式

from apscheduler.schedulers.blocking import BlockingScheduler
import datetime sched = BlockingScheduler()
#每隔5秒运行一次my_job1
@sched.scheduled_job('interval',seconds=5,id='my_job1')
def my_job1():
print 'my_job1 is running, Now is %s' % datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") #每隔5秒运行一次my_job2
@sched.scheduled_job('cron',second='*/5',id='my_job2')
def my_job2():
print 'my_job2 is running, Now is %s' % datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
sched.start()

执行结果:

$my_job2 is running, Now is 2016-12-13 15:09:00
$my_job1 is running, Now is 2016-12-13 15:09:03
$my_job2 is running, Now is 2016-12-13 15:09:05
$my_job1 is running, Now is 2016-12-13 15:09:08
$my_job2 is running, Now is 2016-12-13 15:09:10
$my_job1 is running, Now is 2016-12-13 15:09:13
$my_job2 is running, Now is 2016-12-13 15:09:15
$my_job1 is running, Now is 2016-12-13 15:09:18

使用SQLAlchemy作业存储器存放作业

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime,timedelta
import logging sched = BlockingScheduler()
def my_job():
print 'my_job is running, Now is %s' % datetime.now().strftime("%Y-%m-%d %H:%M:%S")
#使用sqlalchemy作业存储器
url='mysql+mysqldb://root:123456@localhost:3306/scrapy?charset=utf8'
sched.add_jobstore('sqlalchemy',url=url)
#添加作业
sched.add_job(my_job,'interval',id='myjob',seconds=5) 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) sched.start()

执行结果:

$ python scheduler.py
INFO:apscheduler.executors.default:Running job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:26:45 CST)" (scheduled at 2016-12-13 21:26:45.067157+08:00)
my_job is running, Now is 2016-12-13 21:26:45
INFO:apscheduler.executors.default:Job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:26:50 CST)" executed successfully
INFO:apscheduler.executors.default:Running job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:26:50 CST)" (scheduled at 2016-12-13 21:26:50.067157+08:00)
my_job is running, Now is 2016-12-13 21:26:50
INFO:apscheduler.executors.default:Job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:26:50 CST)" executed successfully
INFO:apscheduler.executors.default:Running job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:26:55 CST)" (scheduled at 2016-12-13 21:26:55.067157+08:00)
my_job is running, Now is 2016-12-13 21:26:55
INFO:apscheduler.executors.default:Job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:26:55 CST)" executed successfully
INFO:apscheduler.executors.default:Running job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:27:00 CST)" (scheduled at 2016-12-13 21:27:00.067157+08:00)
my_job is running, Now is 2016-12-13 21:27:00
INFO:apscheduler.executors.default:Job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:27:05 CST)" executed successfully
INFO:apscheduler.executors.default:Running job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:27:05 CST)" (scheduled at 2016-12-13 21:27:05.067157+08:00)
my_job is running, Now is 2016-12-13 21:27:05
INFO:apscheduler.executors.default:Job "my_job (trigger: interval[0:00:05], next run at: 2016-12-13 21:27:05 CST)" executed successfully

APScheduler 浅析的更多相关文章

  1. APScheduler 3.0.1浅析

    简介 APScheduler是一个小巧而强大的Python类库,通过它你可以实现类似Unix系统cronjob类似的定时任务系统.使用之余,阅读一下源码,一方面有助于更好的使用它,另一方面,个人认为a ...

  2. SQL Server on Linux 理由浅析

    SQL Server on Linux 理由浅析 今天的爆炸性新闻<SQL Server on Linux>基本上在各大科技媒体上刷屏了 大家看到这个新闻都觉得非常震精,而美股,今天微软开 ...

  3. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  4. 高性能IO模型浅析

    高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking  ...

  5. netty5 HTTP协议栈浅析与实践

      一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...

  6. Jvm 内存浅析 及 GC个人学习总结

    从诞生至今,20多年过去,Java至今仍是使用最为广泛的语言.这仰赖于Java提供的各种技术和特性,让开发人员能优雅的编写高效的程序.今天我们就来说说Java的一项基本但非常重要的技术内存管理 了解C ...

  7. 从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler

    熟悉WebForm开发的朋友一定都知道,Page类必须实现一个接口,就是IHttpHandler.HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...

  8. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  9. 浅析匿名函数、lambda表达式、闭包(closure)区别与作用

    浅析匿名函数.lambda表达式.闭包(closure)区别与作用 所有的主流编程语言都对函数式编程有支持,比如c++11.python和java中有lambda表达式.lua和JavaScript中 ...

随机推荐

  1. 中国Linux开源镜像站大全

    本文来源:各大开源软件.发行版镜像页面.       请注意这是一个总结,如果您自己搭建了一个小型开源镜像,这里并没有.以下列出的是包含大量不同镜像的站点.       具体配置中,我建议您使用大企业 ...

  2. Linux系统下MongoDB的简单安装与基本操作

    这篇文章主要介绍了Linux系统下MongoDB的简单安装与基本操作,需要的朋友可以参考下   Mongo DB ,是目前在IT行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式,备 ...

  3. MySql 链接字符串

    MySql连接字符串总结 1.本地数据库连接    <connectionStrings>        <add name="ConnectionString" ...

  4. 搭建 yum 仓库

    翻译来自:https://wiki.centos.org/HowTos/CreateLocalRepos 本地仓库 http 仓库 测试 Steps: 1.把rpm包放在一个目录中.可以根据需要在该目 ...

  5. hbase表的多版本读写

    TTL(Time To Live)生存期 hbase表默认保存一个版本的数据 hbase(main):123:0> create 't_name','st1'Created table t_na ...

  6. 前端-javascript-DOM(重点)文档对象模型

    1.DOM概念-文档对象模型 // 什么是DOM ? /* Document Object Model 文档对象模型 面向对象: 三个特性 封装 继承 多态 一个对象: 属性和方法 说 万事万物皆对象 ...

  7. JAVA WEB开发中的会话跟踪

    常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份. Http协议是一种无状态的协议,一旦数据交换完毕,客 ...

  8. MYSQL查询优化:show profile

    为避免之前已经把 SQL 存放在 QCACHE 中, 建议在执行 SQL 时, 强制 SELECT 语句不进行 QCACHE 检测.这样可以提交分析的准确性 mysql> select sql_ ...

  9. getattr()函数详解

    setattr(object,name,value): 作用:设置object的名称为name(type:string)的属性的属性值为value,属性name可以是已存在属性也可以是新属性. get ...

  10. struts2的异常配置

    1:当我们出现异常我们浏览器会直接暴露我们的技术结构,会给我们的项目带来一些安全隐患.2:当这种错误出现,给用户感觉是非常不友好.3:怎么解决 1:如果处理找不到action方法的错误呢? 在Stru ...