APSscheduler

一、概述
1.1、介绍
APScheduler(Advanced Python Scheduler)是Python 轻量级定时任务框架,核心作用是帮你在 Python 程序中实现「定时执行代码」「循环执行代码」, 无需依赖 Linux crontab、Windows 任务计划程序等系统级定时工具,可直接嵌入 Django/Flask 等项目,是纯 Python 生态的定时任务解决方案。
1.2、核心组件
# 四大核心组件
1、调度器(Scheduler):核心入口,管理所有任务的 “添加、删除、暂停、恢复、触发”,是使用 APScheduler 的唯一入口;
       调度器类型
        BlockingScheduler: 阻塞式,会阻塞主线程,适合独立脚本
        BackgroundScheduler: 后台线程运行,不阻塞主线程,适合 Web 应用
        AsyncIOScheduler: 适配 asyncio
        GeventScheduler: 适配 gevent
        TornadoScheduler: 适配 Tornado
        TwistedScheduler: 适配 Twisted
        QtScheduler: 适配 Qt 应用

2、触发器(Trigger):定时任务规则,定义任务 “何时执行”;
      触发器类型
      date: 一次性任务,指定日期时间执行
      interval: 固定间隔执行
      cron: 类似 Linux crontab 的时间表达式

3、任务(Job):你要定时运行的 Python 函数;
4、执行器(Executor):负责执行任务,支持线程池 / 进程池,控制 “同时执行多少个任务”。
        默认使用线程池执行器
        可配置进程池执行器
1.3、任务存储(Job Store)
决定任务配置的保存方式(是否重启后丢失)
| 存储类型               | 特点                           | 适用场景            |
| ------------------    | ----------------------------  | --------------- |
| MemoryJobStore(默认) | 存在内存中,重启后丢失                  | 测试 / 临时任务       |
| SQLAlchemyJobStore    | 存在数据库,重启不丢               |  项目生产环境   |

| redis JobStore        | 存在redis中,支持分布式            | 分布式项目可用
1.4、安装
# 最小化安装,这个会安装核心模块,99%功能覆盖,基本够用。
pip install apscheduler

# 完整安装
pip install apscheduler[all]
这会安装所有可选依赖,包括:
数据库后端支持
Redis 支持               # 用 RedisJobStore 存储任务
MongoDB 支持.        # 用 MongoDBJobStore 存储任务
RethinkDB 支持
ZooKeeper 支持。    
SQLAlchemy 支持     



# 按需安装,你可以根据需求只安装需要的组件:
# 1. 如果你只需要使用数据库存储(推荐大多数情况)
pip install apscheduler[sqlalchemy]
# 2. 使用 Redis 作为作业存储
pip install apscheduler[redis]
# 3. 使用 MongoDB
pip install apscheduler[mongo]
# 4. 使用 etcd
pip install apscheduler[etcd]
# 5. 使用 ZooKeeper
pip install apscheduler[zookeeper]
# 6. 使用 RethinkDB
pip install apscheduler[rethinkdb]
# 7. 使用 Twisted(异步框架)
pip install apscheduler[twisted]
# 8. 使用 Tornado
pip install apscheduler[tornado]
# 9. 使用 asyncio
pip install apscheduler[asyncio]
# 10. 使用 gevent
pip install apscheduler[gevent]
# 11. 使用 Qt
pip install apscheduler[qt]
二、使用
1.1、最小示例
先跑一个最简单的例子,直观感受 APScheduler 的用法:
# 导入核心模块
from apscheduler.schedulers.blocking import BlockingScheduler

# 1. 定义要定时执行的任务(任意 Python 函数)
def say_hello():
    print("Hello APScheduler! 当前时间:", __import__('datetime').datetime.now())

# 2. 创建调度器(BlockingScheduler:阻塞式,适合独立脚本)
scheduler = BlockingScheduler()

# 3. 添加任务:每 5 秒执行一次 say_hello 函数
scheduler.add_job(
    func=say_hello,  # 要执行的函数
    trigger="interval",  # 触发规则:固定间隔
    seconds=5  # 间隔 5 秒
)

# 4. 启动调度器(程序会阻塞在这里,持续执行任务)
if __name__ == '__main__':
    try:
        scheduler.start()
    except KeyboardInterrupt:  # 按 Ctrl+C 停止
        scheduler.shutdown()

运行效果:控制台每 5 秒打印一次 Hello APScheduler! 当前时间:xxxx。
1.2、三种触发器用法介绍

触发器是 APScheduler 的核心,决定任务的执行时间,支持 3 种核心类型,覆盖所有定时场景

1. date 触发器:一次性触发(指定具体时间)
适合 “某个固定时间点执行一次” 的场景(如 “2025 年 12 月 25 日 20:00 执行”)
eg:
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

def task():
    print("一次性任务执行!时间:", datetime.now())

scheduler = BlockingScheduler()

# 方式1:指定具体时间字符串(格式:YYYY-MM-DD HH:MM:SS)
scheduler.add_job(
              task, 
              'date',   # 触发器:固定时间点执行一次
              run_date='2025-12-25 20:00:00',    # 时间点
              id='one_time_task'  # 给任务起个名字
)

scheduler.start()

2、interval 触发器:固定间隔触发
适合 “每隔 N 秒 / 分 / 时 / 天执行” 的场景(如 “每 10 分钟检查一次任务状态”)
from apscheduler.schedulers.blocking import BlockingScheduler

def task():
    print("间隔任务执行!时间:", __import__('datetime').datetime.now())

scheduler = BlockingScheduler()

# 添加任务:每 1 分钟执行一次(支持 seconds/minutes/hours/days/weeks)
scheduler.add_job(
    task,
    'interval',
    minutes=1,  # 间隔 1 分钟
    # 可选:start_date/end_date 限制执行时间范围
    # start_date='2025-12-20 08:00:00',
    # end_date='2025-12-20 18:00:00',
    id='interval_task'
)

scheduler.start()

# 常用参数:
seconds:秒(如 seconds=10 → 每 10 秒);
minutes:分钟(如 minutes=5 → 每 5 分钟);
hours:小时(如 hours=1 → 每小时);
days:天(如 days=1 → 每天);
weeks:周(如 weeks=1 → 每周)。

3、cron 触发器:crontab 表达式触发(最常用)
适合 “复杂时间规则”(如 “每天凌晨 2 点执行”“每周一三五 18:00 执行”),完全兼容 Linux crontab 表达式,是生产环境最常用的触发器。

from apscheduler.schedulers.blocking import BlockingScheduler

def task():
    print("Cron 任务执行!时间:", __import__('datetime').datetime.now())

scheduler = BlockingScheduler()

# 示例1:每天凌晨2点执行
scheduler.add_job(task, 'cron', hour=2, minute=0, id='cron_task1')

# 示例2:每周一、三、五 18:00 执行
scheduler.add_job(task, 'cron', day_of_week='1,3,5', hour=18, minute=0, id='cron_task2')

# 示例3:每月1号 00:00 执行
scheduler.add_job(task, 'cron', day=1, hour=0, minute=0, id='cron_task3')

# 示例4:每15分钟执行一次(和 interval 等效,但更贴合 crontab 习惯)
scheduler.add_job(task, 'cron', minute='*/15', id='cron_task4')

# 示例5:直接传 crontab 字符串(分 时 日 月 周)
scheduler.add_job(task, 'cron', cron_expression='0 2 * * *', id='cron_task5')

scheduler.start()

三、任务管控

APScheduler 支持对任务进行全生命周期管控(增删改查 / 暂停恢复),核心方法如下(以上述示例的 scheduler 为例):

1. 添加任务(已讲)
核心:scheduler.add_job(func, trigger, **trigger_args, id='任务ID', replace_existing=True)
id:任务唯一标识(必填,用于后续管控);
replace_existing=True:如果任务 ID 已存在,替换原有任务(避免重复)。

2. 查询任务
# 查询单个任务(通过ID)
job = scheduler.get_job('cron_task1')
if job:
    print("任务ID:", job.id)
    print("任务状态:", job.status)  # pending/running/paused/finished
    print("下次执行时间:", job.next_run_time)

# 查询所有任务
jobs = scheduler.get_jobs()
for job in jobs:
    print(f"任务 {job.id}:状态={job.status},下次执行={job.next_run_time}")

3、暂停任务
# 暂停单个任务(通过ID)
scheduler.pause_job('cron_task1')

# 暂停所有任务
scheduler.pause_all()

4、恢复任务
# 恢复单个任务
scheduler.resume_job('cron_task1')

# 恢复所有任务
scheduler.resume_all()

5、修改任务(动态调整触发规则)
# 将“每天凌晨2点”改为“每天凌晨3点”
scheduler.modify_job('cron_task1', hour=3)

# 也可通过 job 对象修改
job = scheduler.get_job('cron_task1')
job.modify(hour=3)

6、删除任务
# 删除单个任务(通过ID)
scheduler.remove_job('cron_task1')

# 删除所有任务
scheduler.remove_all_jobs()

7、立即执行任务(手动触发)
# 立即执行指定任务(不影响原有定时规则)
scheduler.run_job('cron_task1')
四、Django 集成
1. 初始化调度器(全局唯一)
在 Django 项目根目录创建 scheduler.py
# scheduler.py
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.django import DjangoJobStore  # Django 数据库存储
from apscheduler.executors.pool import ThreadPoolExecutor
from django.conf import settings

# 初始化调度器(后台式,不阻塞Django)
def init_scheduler():
    scheduler = BackgroundScheduler(timezone=settings.TIME_ZONE)
    
    # 1. 添加Django数据库存储(任务持久化,重启不丢失)
    scheduler.add_jobstore(DjangoJobStore(), 'default')
    
    # 2. 配置执行器(线程池,控制并发数)
    executors = {
        'default': ThreadPoolExecutor(20)  # 同时执行20个任务
    }
    scheduler.configure(executors=executors)
    
    return scheduler

# 全局调度器实例(确保整个Django只有一个)
scheduler = init_scheduler()


2. Django 启动时加载调度器
修改 wsgi.py(或 asgi.py):
# wsgi.py
import os
from django.core.wsgi import get_wsgi_application
from .scheduler import scheduler

os.environ.setdefault('DJANGO_SETTINGS_MODULE', '你的项目名.settings')
application = get_wsgi_application()

# 启动调度器(仅启动一次)
if not scheduler.running:
    scheduler.start()


3. 迁移数据库(创建任务存储表)

python manage.py migrate


4、编写业务任务代码并使用scheduler即可
注意:给任务函数加完整的异常捕获,避免单个任务失败导致调度器崩溃

注意:APScheduler在嵌入django项目时,有个问题,django的uWSGI 等web服务器 一般都是多进程的,多个进程会启动多个scheduler调度器,会导致同一个定时任务被调度多次。需要自己解决这个问题(redis 分布式锁,或者专用进程启动调度器或者数据库锁等等),或者只使用单进程(单进程影响性能,小项目可以考虑)

web应用时可以考虑使用Celery

posted @ 2025-12-15 17:41  有形无形  阅读(2)  评论(0)    收藏  举报