正在进入ing...

python使用apscheduler制作定时任务

发布时间:2022-04-11 浏览量: 521 文章分类: python

之前我有发布过关于使用schedule定时任务的一篇文章,可以查看这里python 方便的定时器库之 schedule-佩恩的博客)

而随着业务的不断变化,我发现在业务中schedule在满足业务上有一些吃力,一部分是我用的异步代码较多,而且时间要求上很灵活。用achedule多了,管理较为困难。这时就发现了一个更加灵活的库APScheduler其实严格意义上来说已经是一个完整的框架了。在某些场景下,比celery好用(我说的)。

安装

pip install apscheduler

使用

先看一个最简单的案例,每5秒执行函数一次

from apscheduler.schedulers.asyncio import AsyncIOScheduler
import asyncio
import os
import datetime

async def run():
    print(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]执行一次")


if __name__ == '__main__':
    executor = AsyncIOScheduler(
        timezone='Asia/Shanghai',
        job_defaults={
            "misfire_grace_time": 3600,  # 允许存在多久时间的任务数
            "max_instances": 200,  # 该定时任务允许最大的实例个数
            "coalesce": False  # 多个任务堆积,是否运行最新的
        }
    )

    executor.add_job(
        run,
        trigger='interval',
        seconds=5,
        coalesce=False,
        misfire_grace_time=3600,
        args=[])

    executor.start()
    print(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]线程开始执行")
    try:
        asyncio.get_event_loop().run_forever()
    except (KeyboardInterrupt, SystemExit):
        pass

虽然对于第一次接触的同学看着可能不是很明白,但是其实还是很简单的。整体分为3部分。

  • executor = AsyncIOScheduler()创建异步任务

  • executor.add_job()、executor.start()添加任务/启动任务

  • asyncio.get_event_loop().run_forever()写入循环任务开始

这里有一个问题要先说一下,就是因为apscheduler是一个功能强大且完善的定时任务框架,而且涉及了5大部分,分别是触发器(trigger)、作业存储(job store)、执行器(executor)、调度器(scheduler)、任务或作业(task)。

我目前也并没有一个项目是完整用到5个模块的。所以我主要还是说我用到的地方,别的地方我会先写上,以后我用到的话,会回来在补充上。

触发器(tigger)

这部分比较简单,APScheduler有三种自带的tigger,基本满足各种刁钻的业务要求了。

  • interval: 固定时间间隔触发

  • date: 特定的时间点触发(作业只会执行一次

  • cron: 在特定时间周期性地触发(量化常用)

executor.add_job(
    run,
    trigger='interval',
    seconds=5,
)

executor.add_job(
    run,
    trigger='corn',
    minute='*/5',
)

executor.add_job(
    run, 
    trigger='cron', 
    year="*", month="*", day="*", hour="15", minute="07", second="00"
)

执行器(executor)

  • BlockingScheduler 阻塞式调度器,适用于只跑调度器的程序

  • BackgroundScheduler后台式调度器,适用于非阻塞的情况,调度器会在后台运行

  • AsyncIOScheduler 我目前比较常用的,可以适用于async任务

  • TornadoSchedulerTornado调度器,还没用过

  • TwistedSchedulerTwisted调度器,还没用过

  • QtSchedulerQt调度器,还没用过

调度器(scheduler)

我在业务中暂时还没有用到,引用网上的说明,有机会尝试后我会在来完善

配置作业存储和执行器可以在调度器中完成,例如添加、修改和移除作业。 调度器主要用到阻塞和后台运行这2种 BlockingScheduler:main_loop就在当前进程的主线程内运行,所以调用start函数后会阻塞当前线程。通过一个threading.Event条件变量对象完成scheduler的定时唤醒。 BackgroundScheduler:和BlockingScheduler基本一样,除了main_loop放在了单独线程里,所以调用start后主线程不会阻塞

任务或作业(task)

目前只是用到add_job添加任务,其余的暂时还没用过。

补充

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    (datime|str)    最早开始日期(包含)
end_date    (datetime|str)    最晚结束日期(包含)
timezone    (datetime.tzinfo|str)    指定时区

interval触发器的参数如下

# 参数 类型  说明
weeks   int 间隔几周
days    int 间隔几天
houres  int 间隔几小时
minutes int 间隔几分钟
seconds int 间隔几秒钟
start_date  datetime/str    开始日期
end_time    datetime/str    结束日期
timezone    dateime.tzinfo/str  时区