APScheduler
概述
APScheduler(advanceded python scheduler)是一个轻量级的Python调度库,它允许你以多种方式安排任务的运行,包括定期执行、定时执行和间隔执行。在实际应用中,APScheduler被广泛用于周期性任务的调度,如数据备份、数据清理等。
APScheduler 的主要特点包括:
轻松灵活地设置定时任务
不依赖于Linux系统的crontab系统定时,独立运行
可以动态添加新的定时任务
提供了简单的 API,方便开发者快速上手
对添加的定时任务可以做持久保存
GitHub:https://github.com/agronholm/apscheduler
文档:https://apscheduler.readthedocs.io/en/latest/userguide.html#starting-the-scheduler
安装
首先,需要安装 APScheduler。可以通过 pip 来安装:
python
pip install apscheduler
基本使用
创建调度器对象
使用APScheduler需要先创建一个调度器对象,可以选择使用不同的调度器类来创建不同类型的调度器,例如BlockingScheduler、BackgroundScheduler等。
python
from apscheduler.schedulers.blocking import BlockingScheduler
scheduler = BlockingScheduler()
定义任务函数
定义任务函数,该函数将会被周期性地调用。
python
def job():
print('Hello, world!')
添加任务
使用调度器对象的add_job方法添加任务。可以指定任务函数、触发器类型、触发器参数等信息。
python
scheduler.add_job(job, 'interval', seconds=5)
在调用scheduler.add_job()
方法添加任务时,第二个参数可以传递一个触发器类型
,表示何时触发该任务。
interval
sql
interval是APScheduler中的一种触发器类型,表示周期性地执行任务。
如果传递interval类型,则需要指定间隔时间,也就是任务执行的时间间隔。
启动调度器
使用start方法启动调度器,开始周期性地执行任务。
python
scheduler.start()
注意:
yaml
BlockingScheduler : 程序会阻塞在这,防止退出
BackgroundScheduler : 程序会立即返回,后台运行
完整代码
python
from apscheduler.schedulers.background import BlockingScheduler
def task():
# 创建定时任务的调度器对象
scheduler = BlockingScheduler()
# 定义定时任务
def job(param1, param2):
print(param1)
print(param2)
print('Hello, world')
# 向调度器中添加定时任务
scheduler.add_job(job, 'interval', seconds=5, args=['Hello', 'world'])
# 启动定时任务调度器工作
# BlockingScheduler:发生阻塞
scheduler.start()
if __name__ == '__main__':
# 执行task
task()
调度器Scheduler
在APScheduler中,调度器(Scheduler)是用于管理和调度任务的核心组件。它负责添加、删除和修改任务,并根据指定的触发器类型执行任务。
常见调度器
BlockingScheduler:阻塞式调度器,在主线程中运行,执行任务时会阻塞主线程
BackgroundScheduler:后台调度器,会创建一个后台线程来执行任务,不会阻塞主线程
AsyncIOScheduler:基于asyncio的异步调度器,适用于Python 3.5及以上版本
TwistedScheduler:基于Twisted框架的调度器,适用于Twisted应用程序
GeventScheduler:基于Gevent协程库的调度器,支持在协程环境中使用
TornadoScheduler:基于Tornado框架的调度器,适用于Tornado应用程序
在使用APScheduler时,需要选择合适的调度器类型,并创建相应的调度器对象。
在框架程序(如Django、Flask)中使用通常使用BackgroundScheduler
python
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.start() # 不会发生阻塞
执行器executors
在APScheduler中,执行器(executors)用于实现任务的执行机制。它负责执行调度器提交的任务,并根据指定的执行策略(如线程池或进程池)来管理任务的执行。
常见执行器
ThreadPoolExecutor:基于线程池的执行器,在单个Python解释器进程中使用多个线程执行任务
ProcessPoolExecutor:基于进程池的执行器,在单个Python解释器进程中使用多个进程执行任务
BlockingScheduler和BackgroundScheduler默认使用ThreadpoolExecutor作为执行器
ThreadPoolExecutor
python
from apscheduler.executors.pool import ThreadPoolExecutor
ThreadPoolExecutor(20) # 最多20个线程同时执行
ProcessPoolExecutor
python
from apscheduler.executors.pool import ProcessPoolExecutor
ProcessPoolExecutor(5) # 最多5个进程同时执行
使用示例
python
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.schedulers.blocking import BlockingScheduler
def task():
# 创建一个包含 10 个线程的线程池执行器
executor = ThreadPoolExecutor(10)
# 在创建调度器时,选择合适的执行器类型,并与调度器对象关联起来
scheduler = BlockingScheduler(executors={'default': executor})
# executors = {'default': ProcessPoolExecutor(3)}
# scheduler = BackgroundScheduler(executors=executors)
# 定义定时任务
def job(param1, param2):
print(param1)
print(param2)
print('Hello, world')
# 向调度器中添加定时任务
scheduler.add_job(job, 'interval', seconds=5, args=['Hello', 'world'])
# 启动定时任务调度器工作
scheduler.start()
if __name__ == '__main__':
# 执行task
task()
触发器Trigger
在APScheduler中,触发器(Trigger)是用于定义任务运行时间的组件。当调度器决定要执行任务时,会根据指定的触发器类型来计算下一次任务的执行时间,并将其添加到任务队列中。
date
指定任务在指定的日期和时间运行。可以使用 run_date 参数来指定运行时间。
python
from datetime import date
# 在2023年3月3日00:00:00执行
scheduler.add_job(job, 'date', run_date=date(2023, 3, 3))
# 在2023年3月3日17:30:10
scheduler.add_job(job, 'date', run_date=datetime(2023, 3, 3, 17, 30, 10))
scheduler.add_job(job, 'date', run_date='2023-03-03 17:30:10')
# 立即执行
scheduler.add_job(job, 'date')
scheduler.start()
interval
周期性地执行任务,每隔一段时间就触发一次任务
weeks:表示周期性执行任务的周数
days:表示周期性执行任务的天数
hours:表示周期性执行任务的小时数
minutes:表示周期性执行任务的分钟数
seconds:表示周期性执行任务的秒数
start_date:表示开始执行任务的起始时间点(日期字符串或datetime对象)
end_date:表示停止执行任务的结束时间点(日期字符串或datetime对象)
timezone:表示用于计算任务执行时间的时区对象,默认为系统本地时区
python
from datetime import datetime
# 每两小时执行一次
scheduler.add_job(job, 'interval', hours=2)
# 每隔 5 秒执行任务
scheduler.add_job(job, 'interval', seconds=5)
# 每隔30分钟执行一次,从当前时间(datetime.now())开始执行,直到 2025 年底(end_date='2025-12-31')
scheduler.add_job(job, 'interval', minutes=30, start_date=datetime.now(), end_date='2025-12-31')
# 在2022年01月01日09:30:00 到2023年12月31日的时间内,每两小时执行一次
scheduler.add_job(job, 'interval', hours=2, start_date='2022-01-01 09:30:00', end_date='2023-12-31 10:00:00')
cron
使用类似于 Unix 中的 cron 表达式来指定任务的执行时间。cron 表达式由 6 个时间字段组成,分别表示秒、分钟、小时、日期、月份和星期几。
字段 | 允许值 | 允许的特殊字符 |
---|---|---|
秒 | 0-59 | , - * / |
分钟 | 0-59 | , - * / |
小时 | 0-23 | , - * / |
日 | 1-31 | , - * ? / L W |
月 | 1-12或JAN-DEC | , - * / |
周几 | 0-6或SUN-SAT | , - * ? / L # |
特殊字符含义如下:
特殊字符 | 描述 |
---|---|
* | 代表所有可能的值 |
- |
代表区间,例如 10-12 表示从10到12 |
, | 代表枚举,例如 MON,WED,FRI 表示星期一、三、五 |
/ | 代表步长,例如 */5 表示每5个单位(秒、分、时等) |
? | 仅在日和周几两个字段上使用,表示不指定具体的值 |
L | 仅在日和周几两个字段上使用,表示为月末或周末(最后一个工作日或非周末) |
W | 仅在日字段上使用,表示距离给定日期最近的工作日 |
# |
仅在周几字段上使用,表示第几个周几,例如 3#2 表示每个月的第二个周二 |
python
year (int|str) -- 4-digit year
month (int|str) -- month (1-12)
day (int|str) -- day of the (1-31)
week (int|str) -- ISO week (1-53)
day_of_week (int|str) -- number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun)
hour (int|str) -- hour (0-23)
minute (int|str) -- minute (0-59)
second (int|str) -- second (0-59)
start_date (datetime|str) -- earliest possible date/time to trigger on (inclusive)
end_date (datetime|str) -- latest possible date/time to trigger on (inclusive)
timezone (datetime.tzinfo|str) -- time zone to use for the date/time calculations (defaults to scheduler timezone)
python
# 在1、2、3、11、12月的第1个周五的00:00, 01:00, 02:00和03:00 执行
scheduler.add_job(job, 'cron', month='1-3,11-12', day='1rd fri', hour='0-3')
# 每周一至周五的9点30分执行
scheduler.add_job(job, 'cron', hour=9, minute=30, day_of_week='mon-fri')
# 在2023年3月3日前的周一到周五的5:30执行
scheduler.add_job(job, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2023-03-03')
其他
任务管理
方式1
python
job = scheduler.add_job(func, 'interval', minutes=2) # 添加任务
job.remove() # 删除任务
job.pause() # 暂定任务
job.resume() # 恢复任务
方式2
python
scheduler.add_job(func, 'interval', minutes=2, id='my_job_id') # 添加任务
scheduler.remove_job('my_job_id') # 删除任务
scheduler.pause_job('my_job_id') # 暂定任务
scheduler.resume_job('my_job_id') # 恢复任务
调整任务调度周期
python
job.modify(max_instances=6, name='Alternate name')
scheduler.reschedule_job('my_job_id', trigger='cron', minute='*/5')
停止APScheduler运行
python
scheduler.shutdown()