看了一大堆文章帖子,总算从各种定义、参数中爬了出来。
现在总结一下APScheduler定时框架学习结果
功能:Python定时任务框架。提供了基于日期,固定时间间隔及crontab类型的任务,并且可以持久化任务,并以daemon方式运行应用
我的理解:一个工具包,可以方便地添加、存储定时任务,并按时调度、执行
一、简单案例
1 安装包
pip install apscheduler
2、最简功能代码
from apscheduler.schedulers.blocking import BlockingScheduler # 引用阻塞式调度器
from datetime import datetime
# 定时任务
def job():
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# 创建阻塞式调度器BlockingScheduler
scheduler = BlockingScheduler()
# 添加任务
scheduler.add_job(job, 'interval', seconds=3) # 利用内置触发器(trigger)添加定时任务
# 执行任务
scheduler.start() # 执行调度器中存储的定时任务
以上代码实现每3秒钟输出一次当前时间
对应APScheduler的概念,即一次完整的定时任务执行包含了:
(1)定义定时任务job()
(2)创建调度器
(3)通过add_job添加到作业存储,添加时利用触发器明确触发条件,
(4)通过调度器执行作业存储中的定时任务(此处执行器是用默认的)
二、框架组成
APScheduler五个组成分别为:触发器(trigger),作业存储(job store),执行器(executor),调度器(scheduler)、任务或作业(task)。
1、触发器(trigger)
APScheduler 有三种内建的 trigger:
interval: 固定时间间隔触发
date: 特定的时间点触发(作业只会执行一次)
cron: 在特定时间周期性地触发(量化常用)
比如:
sched.add_job(get_candle, 'cron', minute='*/5') # 每隔5分钟获取K线数据
cron触发器参数用法详见附录
2、调度器 (Scheduler)
配置作业存储和执行器可以在调度器中完成,例如添加、修改和移除作业。
调度器主要用到阻塞和后台运行这2种
BlockingScheduler:main_loop就在当前进程的主线程内运行,所以调用start函数后会阻塞当前线程。通过一个threading.Event条件变量对象完成scheduler的定时唤醒。
BackgroundScheduler:和BlockingScheduler基本一样,除了main_loop放在了单独线程里,所以调用start后主线程不会阻塞
(1)BlockingScheduler简单应用
from apscheduler.schedulers.blocking import BlockingScheduler
import time
def my_job():
print('hello world')
scheduler = BlockingScheduler()
scheduler.add_job(my_job, 'interval', seconds=5)
scheduler.start()
while (True):
print('main 1s')
time.sleep(1)
上面的例子表示每隔5s执行一次my_job函数,输出hello world
当前进程不结束一直运行
但while(True):之后的循环不会被执行,主程序运行到start()已被阻塞(阻塞型调度)
(2)BackgroundScheduler简单应用
from apscheduler.schedulers.background import BackgroundScheduler
def job3():
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
print("I'm working job_3")
scheduler = BackgroundScheduler()
scheduler.add_job(job3, 'interval', seconds=3) #间隔3秒钟执行一次
scheduler.start()
特别说明:
我在windows环境下用BackgroundScheduler,运行以上代码无效。具体表现是运行后程序终止,调度器中的定时任务也没有在控制台按计划输出。
网上普遍的解决方案:
BackgroundScheduler 运行在Backgroud,但是并不会阻止主程序自己终止,而主程序终止后,BackgroundScheduler 也会终止。
start()启动调度器后添加代码:
while True:
time.sleep(1)
通过无限循环让主程序和scheduler 一直运行,而如果想终止,可以ctrl + C
这种方式其实不能算后台运行模式,还是变相改成了阻塞式
可能是我环境设置有什么问题,先记录,后续再看怎么改进
官网上也说明后台调度start()后会结束脚本
Pycharm平台中,写入.py文件直接run,不会启动后台运行
解决方案:
写入console,或者右键选择run file in python console
可以正常后台运行
3、任务调整(对job的操作)
(1)添加job
# 方式1
scheduler.add_job(job, "cron", day_of_week="1-5", hour=6, minute=30)
# 方式2
# 装饰器
@sched.scheduled_job('interval', id='my_job_id', seconds=5)
def job_function():
print("Hello World")
(1.2)添加带参数的job
def job(a, b, c):
print "job1:", a,b,c
sched.add_job(job, 'interval', seconds=1, args=["a", "b", "c"])
sched.add_job(job, 'interval', seconds=1, kwargs={"a": "a", "b": "b", "c": "c"})
(2)移除job
# 方式1
scheduler.remove_job('my_job_id')
# 方式2
job.remove()
(3)暂停job
apscheduler.job.Job.pause()
apscheduler.schedulers.base.BaseScheduler.pause_job()
(4)获取job列表
get_jobs()
print_jobs()
(5)修改job
除了 jobID 之外 job 的所有属性都可以修改,使用 apscheduler.job.Job.modify() 或者 modify_job() 修改一个 job 的属性
job.modify(max_instances=6, name='Alternate name')
modify_job('my_job_id', trigger='cron', minute='*/5')
(6)关闭job
默认情况下调度器会等待所有的 job 完成后,关闭所有的调度器和作业存储。将 wait 选项设置为 False 可以立即关闭。
scheduler.shutdown()
scheduler.shutdown(wait=False)
以上这些可以满足异步任务基本需要了。
参考文献:
github:https://github.com/agronholm/apscheduler
官网文档:https://apscheduler.readthedocs.io/en/latest/
附录:
cron触发器参数如下:
year (int|str) – 年,4位数字
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) – 指定时区
示例:
# 在6、7、8、11、12月的第三个周五的00:00, 01:00, 02:00和03:00 执行
sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
# 在2014年5月30日前的周一到周五的5:30执行
sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2014-05-30')