轻松掌握APScheduler:一个Python定时任务调度利器

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()
相关推荐
龙哥说跨境25 分钟前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
monkey_meng26 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马29 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng32 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
小白学大数据41 分钟前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin
flashman91142 分钟前
python在word中插入图片
python·microsoft·自动化·word
菜鸟的人工智能之路1 小时前
桑基图在医学数据分析中的更复杂应用示例
python·数据分析·健康医疗
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
秃头佛爷3 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
深度学习lover4 小时前
<项目代码>YOLOv8 苹果腐烂识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·苹果腐烂识别