APScheduler 是一个跨平台的定时框架
安装
pip install apscheduler
理解基本概念
1. 触发器 (triggers)
触发器包含调度逻辑。 每个作业都有自己的触发器,用于确定何时应该运行作业。 除了初始配置之外,触发器完全是无状态的。
2. 作业存储器 (job stores)
作业存储器安排预定的工作。 默认作业存储只是将作业保留在内存中,但也可以将它们存储在各种类型的数据库中。 作业的数据在保存到持久性作业存储时会被序列化,并在从其中加载时进行反序列化。 作业存储(默认存储除外)不会将作业数据保留在内存中,而是充当中间人,用于在后端保存,加载,更新和搜索作业。 绝不能在调度程序之间共享作业存储。
3. 执行器 (executors)
执行器是将指定的作业(调用函数)提交到线程池或进程池中运行,当任务完成时,执行器通知调度器触发相应的事件。
4. 调度器 (schedulers)
通过它配置作业存储器、执行器和触发器,添加、修改和删除任务。调度器协调触发器、作业存储器、执行器的运行,通常只有一个调度程序运行在应用程序中,开发人员通常不需要直接处理作业存储器、执行器或触发器,配置作业存储器和执行器是通过调度器来完成的。
常见的调度器
- BlockingScheduler: 阻塞式调度器, 适用于只跑调度器的程序
from apscheduler.schedulers.blocking import BlockingScheduler
- BackgroundScheduler: 后台调度器, 适用于非阻塞的情况,调度器会在后台独立运行
from apscheduler.schedulers.background import BackgroundScheduler
- AsyncIOScheduler:适合于使用asyncio框架(一个异步框架)的情况
- GeventScheduler: 适合于使用gevent框架(高性能的Python并发框架)的情况
- TornadoScheduler: 适合于使用Tornado框架(一个web框架)的应用
- TwistedScheduler: 适合使用Twisted框架的应用
- QtScheduler: 适合使用QT的情况
选择合适的触发器
1. date: 想让程序在在某个固定的时间运行
# 只写主要程序
# 给触发器传入'date', 表示在2019年8月8日 凌晨01:00:00执行一次
scheduler.add_job(main, 'date', run_date='2019-08-08 01:00:00')
2. interval:想让程序以固定的时间间隔运行
# 给触发器传入'interval', 表示自从运行程序开始, 每隔120秒就执行一次
scheduler.add_job(main, 'interval', seconds=120)
3. cron:想让程序在一天中的某个时间定期运行
# 给触发器传入'cron',表示每天的17:10分执行任务,时间可以是数字,也可是字符串
scheduler.add_job(main, 'cron', hour=17, minute=10 )
4. calendarinterval:当您想要在一天中的特定时间以日历为基础的间隔运行作业时使用
配置调度程序
APScheduler提供了许多不同的方法来配置调度程序。您可以使用配置字典,也可以将选项作为关键字参数传递。您还可以先实例化调度程序,然后添加作业并配置调度程序。
# 导入模块
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
# 定义一个拟调度的函数
def get_now_time():
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
if __name__ == "__main__":
# 实例化一个调度程序
scheduler = BlockingScheduler()
# 给调度器添加作业, 给触发器传递 "cron", 表示在每天的17:10分执行任务
scheduler.add_job(get_now_time, 'cron', hour=17, minute=10 )
# 启动调度程序
scheduler.start()
启动调度器
启动调度器是只需调用start()即可。除了BlockingScheduler,非阻塞调度器都会立即返回,可以继续运行之后的代码,比如添加任务等。
添加任务
- 最常用 add_job() 会返回一个apscheduler.job.Job实例,这样就可以在运行时,修改或删除任务。
- 最方便 scheduled_job() 但是运行时,不能修改任务。
移除任务
- 调用remove_job(),参数为:任务ID,任务储存器名称
job = scheduler.add_job(get_now_time, 'cron', hour=17, minute=10 )
job.remove()
- 在通过add_job()创建的任务实例上调用remove()方法
scheduler.add_job(get_now_time, 'interval', minutes=2, id='my_job_id')
scheduler.remove_job('my_job_id')
暂停/恢复任务
通过任务实例或调度器,就能暂停和恢复任务。如果一个任务被暂停了,那么该任务的下一次运行时间就会被移除。在恢复任务前,运行次数计数也不会被统计。
- 暂停任务
#暂停任务,有以下两个方法:
apscheduler.job.Job.pause()
apscheduler.schedulers.base.BaseScheduler.pause_job()
- 恢复任务
apscheduler.job.Job.resume()
apscheduler.schedulers.base.BaseScheduler.resume_job()
获取/打印任务列表
- 获取任务列表
通过get_jobs()就可以获得一个可修改的任务列表。get_jobs()第二个参数可以指定任务储存器名称,那么就会获得对应任务储存器的任务列表。 - 打印任务列表
print_jobs()可以快速打印格式化的任务列表,包含触发器,下次运行时间等信息。
修改任务
- 通过apscheduler.job.Job.modify()或modify_job(),你可以修改任务当中除了id的任何属性。
# max_instances参数, 指定任务设置最大实例并行数
job.modify(max_instances=6, name='Alternate name')
- 通过apscheduler.job.Job.reschedule()或reschedule_job()来重新调度任务(就是改变触发器)
scheduler.reschedule_job('my_job_id', trigger='cron', minute='*/5')
关闭调度器
默认情况下,调度器会先把正在执行的任务处理完,再关闭任务储存器和执行器。但是,如果你就直接关闭可添加参数 wait=False
scheduler.shutdown(wait=False)
暂停/恢复任务进程
- 暂停任务
scheduler.pause()
- 恢复任务
scheduler.resume()
# 可以在调度器启动时,默认所有任务设为暂停状态
scheduler.start(paused=True)