APScheduler 学习笔记
1. 简介
pass
2. 安装
2.1 使用pip安装
pip install apscheduler
2.2 下载后执行python
下载地址:APScheduler · PyPI
python setup.py install
3 基本概念
APScheduler 有四种组件分别为
- triggers
- job stores
- executors
- schedulers
eg:
from apscheduler.schedulers.blocking import BlockingScheduler
import time
# 实例化一个调度器
scheduler = BlockingScheduler()
def job1():
print "%s: 执行任务" % time.asctime()
# 添加任务并设置触发方式为3s一次
scheduler.add_job(job1, 'interval', seconds=3)
# 开始运行调度器
scheduler.start()
4 schedulers任务调度组件
调度器 | 说明 |
---|---|
BlockingScheduler | 调度器是应用中唯一要运行的东西时。 |
BackgroundScheduler | 当没有运行任何其他框架,并希望调度器在应用的后台执行时使用。 |
AsyncIOScheduler | 程序使用了asyncio(一个异步框架)时使用。 |
GeventScheduler | 程序使用了gevent(高性能的Python并发框架)时使用。 |
TornadoScheduler | 程序基于Tornado(一个web框架)时使用。 |
TwistedScheduler | 程序基于Tornado(一个web框架)的时候使用。 |
QtScheduler | 应用是一个Qt应用的时候可以使用 |
4.1 BlockingScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
import time
scheduler = BlockingScheduler()
def job_test():
print "%s: 执行任务" % time.asctime()
scheduler.add_job(job_test, 'interval', seconds=3)
scheduler.start()
4.2 BackgroundScheduler
from apscheduler.schedulers.background import BackgroundScheduler
import time
scheduler = BackgroundScheduler()
def job_test():
print "%s: 执行任务" % time.asctime()
scheduler.add_job(job_test, 'interval', seconds=3)
scheduler.start()
4.3 AsynclOScheduler
from apscheduler.schedulers.asyncio import AsyncIOScheduler
try:
import asyncio
except ImportError:
import trollius as asyncio
...
...
# while True:pass
try:
asyncio.get_event_loop().run_forever()
except (KeyboardInterrupt, SystemExit):
pass
4.4 GeventScheduler
from apscheduler.schedulers.gevent import GeventScheduler
...
...
g = scheduler.start()
# while True:pass
try:
g.join()
except (KeyboardInterrupt, SystemExit):
pass
4.5 TornadoScheduler
from tornado.ioloop import IOLoop
from apscheduler.schedulers.tornado import TornadoScheduler
...
...
# while True:pass
try:
IOLoop.instance().start()
except (KeyboardInterrupt, SystemExit):
pass
4.6 TwistedScheduler:Twisted
from twisted.internet import reactor
from apscheduler.schedulers.twisted import TwistedScheduler
...
...
# while True:pass
try:
reactor.run()
except (KeyboardInterrupt, SystemExit):
pass
4.7 调度器操作
开启 scheduler.start()
关闭 scheduler.shutdown()
暂停 scheduler.pause()
继续 scheduler.resume()
5. triggers任务触发器组件
当调度作业的时,需要为这个作业选择一个触发器,用来描述这个作业何时被触,任务触发器组件,提供有三种内置的任务触发方式:
触发方式类型 | 说明 |
---|---|
date | 在某个时间点只运行一次作业时使用 |
interval | 按固定的时间间隔运行作业时使用 |
cron | 类linux下的crontab格式,属于定时调度 |
5.1 一次性调度data
参数 | 格式 | 说明 |
---|---|---|
run_date | datetime/str | 在某个时间点只运行一次作业时使用 |
timezone | datetime.tzinfo/str | 指定时区 |
eg:
# 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'])
5.2 间隔调度interval
参数 | 格式 | 说明 |
---|---|---|
year | int/str | 年 |
month | int/str | 月(范围1-12) |
day | int/str | 日(范围1-31) |
week | int/str | 周(范围1-53) |
day_of_week | int/str | 一周之内的第几天(范围0-6 或者 mon,tue,wed,thu,fri,sat,sun) |
hour | int/str | 时(范围0-23) |
minute | int/str | 分(范围0-59) |
second | int/str | 秒(范围0-59) |
start_date | datetime/str | 最早开始时间(包含指定时间) |
end_date | datetime/str | 最晚结束时间(包含指定时间) |
timezone | datetime.tzinfo/str | 指定时区 |
eg:
5.3 定时调度cron
参数 | 格式 | 说明 |
---|---|---|
year | int/str | 年 |
month | int/str | 月(范围1-12) |
day | int/str | 日(范围1-31) |
week | int/str | 周(范围1-53) |
day_of_week | int/str | 一周之内的第几天(范围0-6 或者 mon,tue,wed,thu,fri,sat,sun) |
hour | int/str | 时(范围0-23) |
minute | int/str | 分(范围0-59) |
second | int/str | 秒(范围0-59) |
start_date | datetime/str | 最早开始时间(包含指定时间) |
end_date | datetime/str | 最晚结束时间(包含指定时间) |
timezone | datetime.tzinfo/str | 指定时区 |
eg:
# 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')
6.job_stores 任务保存组件
提供任务保存方式
6.1. base
6.2. memory
6.3. mongodb
scheduler.add_jobstore('mongodb', collection='example_jobs')
6.4. redis
scheduler.add_jobstore('redis', jobs_key='example.jobs', run_times_key='example.run_times')
6.6. rethinkdb
scheduler.add_jobstore('rethinkdb', database='apscheduler_example')
6.7. sqlalchemy
scheduler.add_jobstore('sqlalchemy', url=url)
6.7. zookeeper
scheduler.add_jobstore('zookeeper', path='/example_jobs')
Django中使用示例:
scheduler.add_jobstore(DjangoJobStore(), "default")
7. executors 任务调度组件
7.1 base
pass
7.2 debug
pass
7.3 gevent
pass
7.4 pool(max_workers=10)
pass
7.5 twisted
pass
8. 任务操作
8.1 add_job添加任务
如果使用了任务的存储,开启时最好添加replace_existing=True,否则每次开启都会创建任务的副本
开启后任务不会马上启动,可修改trigger参数
8.2 remove_job删除任务
# 根据任务实例删除
job = scheduler.add_job(myfunc, 'interval', minutes=2)
job.remove()
# 根据任务id删除
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
scheduler.remove_job('my_job_id')
8.3 pause_job暂停任务
8.4 resume_job继续任务
job = scheduler.add_job(myfunc, 'interval', minutes=2)
# 根据任务实例
job.pause()
job.resume()
# 根据任务id暂停
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
scheduler.pause_job('my_job_id')
scheduler.resume_job('my_job_id')
8.5 modify 任务修饰
job.modify(max_instances=6, name='Alternate name')
8.6 reschedule_job重设任务
scheduler.reschedule_job('my_job_id', trigger='cron', minute='*/5')
调度示例(摘录于https://zhuanlan.zhihu.com/p/95563033)
import asyncio
import datetime
from apscheduler.events import EVENT_JOB_EXECUTED
from apscheduler.executors.asyncio import AsyncIOExecutor
from apscheduler.jobstores.redis import RedisJobStore # 需要安装redis
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.cron import CronTrigger
# 定义jobstore 使用redis 存储job信息
default_redis_jobstore = RedisJobStore(
db=2,
jobs_key="apschedulers.default_jobs",
run_times_key="apschedulers.default_run_times",
host="127.0.0.1",
port=6379,
password="test"
)
# 定义executor 使用asyncio是的调度执行规则
first_executor = AsyncIOExecutor()
# 初始化scheduler时,可以直接指定jobstore和executor
init_scheduler_options = {
"jobstores": {
# first 为 jobstore的名字,在创建Job时直接直接此名字即可
"default": default_redis_jobstore
},
"executors": {
# first 为 executor 的名字,在创建Job时直接直接此名字,执行时则会使用此executor执行
"first": first_executor
},
# 创建job时的默认参数
"job_defaults": {
'coalesce': False, # 是否合并执行
'max_instances': 1 # 最大实例数
}
}
# 创建scheduler
scheduler = AsyncIOScheduler(**init_scheduler_options)
# 启动调度
scheduler.start()
second_redis_jobstore = RedisJobStore(
db=2,
jobs_key="apschedulers.second_jobs",
run_times_key="apschedulers.second_run_times",
host="127.0.0.1",
port=6379,
password="test"
)
scheduler.add_jobstore(second_redis_jobstore, 'second')
# 定义executor 使用asyncio是的调度执行规则
second_executor = AsyncIOExecutor()
scheduler.add_executor(second_executor, "second")
# *********** 关于 APScheduler中有关Event相关使用示例 *************
# 定义函数监听事件
def job_execute(event):
"""
监听事件处理
:param event:
:return:
"""
print(
"job执行job:
code => {}
job.id => {}
jobstore=>{}".format(
event.code,
event.job_id,
event.jobstore
))
# 给EVENT_JOB_EXECUTED[执行完成job事件]添加回调,这里就是每次Job执行完成了我们就输出一些信息
scheduler.add_listener(job_execute, EVENT_JOB_EXECUTED)
# *********** 关于 APScheduler中有关Job使用示例 *************
# 使用的是asyncio,所以job执行的函数可以是一个协程,也可以是一个普通函数,AsyncIOExecutor会根据配置的函数来进行调度,
# 如果是协程则会直接丢入到loop中,如果是普通函数则会启用线程处理
# 我们定义两个函数来看看执行的结果
def interval_func(message):
print("现在时间: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
print("我是普通函数")
print(message)
async def async_func(message):
print("现在时间: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
print("我是协程")
print(message)
# 将上述的两个函数按照不同的方式创造触发器来执行
# *********** 关于 APScheduler中有关Trigger使用示例 *************
# 使用Trigger有两种方式,一种是用类创建使用,另一个是使用字符串的方式
# 使用字符串指定别名, scheduler初始化时已将其定义的trigger加载,所以指定字符串可以直接使用
if scheduler.get_job("interval_func_test", "default"):
# 存在的话,先删除
scheduler.remove_job("interval_func_test", "default")
# 立马开始 2分钟后结束, 每10s执行一次 存储到first jobstore second执行
scheduler.add_job(interval_func, "interval",
args=["我是10s执行一次,存放在jobstore default, executor default"],
seconds=10,
id="interval_func_test",
jobstore="default",
executor="default",
start_date=datetime.datetime.now(),
end_date=datetime.datetime.now() + datetime.timedelta(seconds=240))
# 先创建tigger
trigger = IntervalTrigger(seconds=5)
if scheduler.get_job("interval_func_test_2", "second"):
# 存在的话,先删除
scheduler.remove_job("interval_func_test_2", "second")
# 每隔5s执行一次
scheduler.add_job(async_func, trigger, args=["我是每隔5s执行一次,存放在jobstore second, executor = second"],
id="interval_func_test_2",
jobstore="second",
executor="second")
# 使用协程的函数执行,且使用cron的方式配置触发器
if scheduler.get_job("cron_func_test", "default"):
# 存在的话,先删除
scheduler.remove_job("cron_func_test", "default")
# 立马开始 每10s执行一次
scheduler.add_job(async_func, "cron",
args=["我是 每分钟 30s 时执行一次,存放在jobstore default, executor default"],
second='30',
id="cron_func_test",
jobstore="default",
executor="default")
# 先创建tigger
trigger = CronTrigger(second='20,40')
if scheduler.get_job("cron_func_test_2", "second"):
# 存在的话,先删除
scheduler.remove_job("cron_func_test_2", "second")
# 每隔5s执行一次
scheduler.add_job(async_func, trigger, args=["我是每分钟 20s 40s时各执行一次,存放在jobstore second, executor = second"],
id="cron_func_test_2",
jobstore="second",
executor="second")
# 使用创建trigger对象直接创建
print("启动: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
asyncio.get_event_loop().run_forever()
输出结果部分截取
启动之后,每隔5s运行一次的JOB
启动: 2019-12-05 14:13:11
【这部分是定义的协程函数输出的内容】
现在时间: 2019-12-05 14:13:16
我是协程
我是每隔5s执行一次,存放在jobstore second, executor = second
【这部分是监听job执行完成之后的回调输出】
job执行job: code => 4096
job.id => interval_func_test_2
jobstore=>second
在20s和40s时各执行一次的Job
现在时间: 2019-12-05 14:13:20
我是协程
我是每分钟 20s 40s时各执行一次,存放在jobstore second, executor = second
job执行
job: code => 4096
job.id => cron_func_test_2
jobstore=>second
每隔10s执行一次的job
现在时间: 2019-12-05 14:13:21
我是普通函数
我是10s执行一次,存放在jobstore default, executor default
现在时间: 2019-12-05 14:13:21
我是协程
我是每隔5s执行一次,存放在jobstore second, executor = second
job执行job: code => 4096
job.id => interval_func_test
jobstore=>default
job执行
job: code => 4096
job.id => interval_func_test_2
jobstore=>second
每隔5s执行一次的Job
现在时间: 2019-12-05 14:13:26
我是协程
我是每隔5s执行一次,存放在jobstore second, executor = second
job执行
job: code => 4096
job.id => interval_func_test_2
jobstore=>second
每分钟30s时执行一次
现在时间: 2019-12-05 14:13:30
我是协程
我是 每分钟 30s 时执行一次,存放在jobstore default, executor default
job执行
job: code => 4096
job.id => cron_func_test
jobstore=>default