Python使用APScheduler实现定时任务

一、简介

APScheduler是基于Quartz的一个Python定时任务框架。提供了基于日期、固定时间间隔以及crontab类型的任务,并且可以持久化任务。在线文档:https://apscheduler.readthedocs.io/en/latest/userguide.html

二、安装APScheduler

activate python_test
pip install apscheduler

三、基本概念

APScheduler有四大组件:

1、触发器 triggers 

触发器包含调度逻辑。每个作业都有自己的触发器,用于确定下一个任务何时运行。除了初始配置之外,触发器是完全无状态的。有三种内建的trigger:
(1)date: 特定的时间点触发
(2)interval: 固定时间间隔触发
(3)cron: 在特定时间周期性地触发

2、任务储存器 job stores

用于存放任务,把任务存放在内存(为默认MemoryJobStore)或数据库中。

3、执行器 executors

执行器是将任务提交到线程池或进程池中运行,当任务完成时,执行器通知调度器触发相应的事件。

4、调度器 schedulers

把上方三个组件作为参数,通过创建调度器实例来运行根据开发需求选择相应的组件,下面是不同的调度器组件:
BlockingScheduler 阻塞式调度器:适用于只跑调度器的程序。
BackgroundScheduler 后台调度器:适用于非阻塞的情况,调度器会在后台独立运行。
AsyncIOScheduler AsyncIO调度器,适用于应用使用AsnycIO的情况。
GeventScheduler Gevent调度器,适用于应用通过Gevent的情况。
TornadoScheduler Tornado调度器,适用于构建Tornado应用。
TwistedScheduler Twisted调度器,适用于构建Twisted应用。
QtScheduler Qt调度器,适用于构建Qt应用。

四、使用步骤

1、新建一个调度器schedulers
2、添加调度任务
3、运行调度任务

五、使用实例

1、触发器date

特定的时间点触发,只执行一次。参数如下:
参数
说明
run_date (datetime 或 str)
作业的运行日期或时间
timezone (datetime.tzinfo 或 str)
指定时区
使用例子:
from datetime import datetime, date  # 时间
from apscheduler.schedulers.blocking import BlockingScheduler  # 定时任务
from demo import hello, myapp  # 自己写的包
from JobStores import job

'''
三种模式:
(1)date: 特定的时间点触发,最基本的一种调度,作业只会执行一次。
(2)interval: 固定时间间隔触发(在某个时间范围内间隔多长时间执行一次)
(3)cron: 在特定时间周期性地触发(cron 和Linux crontab格式兼容,最为强大)
参数说明:
run_date (datetime 或 str): 作业的运行日期或时间
timezone (datetime.tzinfo 或 str): 指定时区
'''

scheduler = BlockingScheduler()

# 在 2021-9-6 运行一次 hello.hello_func 方法
scheduler.add_job(hello.hello_func, 'date', run_date=date(2021, 9, 6))
scheduler.add_job(job.hello, 'date', run_date=date(2021, 9, 6), args=['小哈'])

# 在 2021-9-6 09:55:00 运行一次 hello.read_hello 方法
scheduler.add_job(hello.read_hello, 'date', run_date=datetime(2021, 9, 6, 9, 55))
scheduler.add_job(job.hello, 'date', run_date=datetime(2021, 9, 6, 9, 55), args= ['科比',42])

# 在 2021-9-6 09:55:10 运行一次 myapp.myapp_func 方法
scheduler.add_job(myapp.myapp_func, 'date', run_date='2021-9-6 09:55:10')
scheduler.add_job(job.hello, 'date', run_date='2021-9-6 09:55:10', args= ['蓝精灵', 1000, 'unknown'])

scheduler.start()

2、触发器interval

固定时间触发。参数如下:
参数
说明
weeks(int)
间隔几周
days(int)
间隔几天
hours(int)
间隔几小时
minutes(int)
间隔几分钟
seconds(int)
间隔几秒钟
start_date (datetime 或 str)
开始日期
end_date (datetime 或 str)
结束日期
timezone (datetime.tzinfo 或str)
时区
使用例子:
from apscheduler.schedulers.blocking import BlockingScheduler  # 定时任务
from JobStores import job

'''
三种模式:
(1)date: 特定的时间点触发,最基本的一种调度,作业只会执行一次。
(2)interval: 固定时间间隔触发(在某个时间范围内间隔多长时间执行一次)
(3)cron: 在特定时间周期性地触发(cron 和Linux crontab格式兼容,最为强大)
参数说明:
weeks (int): 间隔几周
days (int): 间隔几天
hours (int): 间隔几小时
minutes (int): 间隔几分钟
seconds (int): 间隔多少秒
start_date (datetime 或 str): 开始日期
end_date (datetime 或 str): 结束日期
timezone (datetime.tzinfo 或str): 时区
'''

scheduler = BlockingScheduler()

# 间隔30秒执行一次job.hello
scheduler.add_job(job.hello, 'interval', seconds=30, args=['小哈'])

# 间隔一分钟执行一次job.hello
scheduler.add_job(job.hello, 'interval', minutes=1, args=['科比', 42])

# 间隔一分半执行一次job.hello
scheduler.add_job(job.hello, 'interval', minutes=1, seconds=30, args=['蓝精灵', 1000, 'unknown'])

# 间隔一分半 并且只在[2021-09-06 10:30:00,2021-09-06 10:33:00)]这个时间区间内执行job.hello
scheduler.add_job(job.hello, 'interval', minutes=1, seconds=30, start_date='2021-09-06 10:30:00',
                  end_date='2021-09-06 10:33:00', args=['王铁锤', 38, 'Woman'])

scheduler.start()

# 大家好,我的名字是王铁锤,今年38岁,性别Woman,现在时间为:2021-09-06 10:30:00
# 大家好,我的名字是小哈,今年18岁,性别Man,现在时间为:2021-09-06 10:30:08
# 大家好,我的名字是小哈,今年18岁,性别Man,现在时间为:2021-09-06 10:30:38
# 大家好,我的名字是科比,今年42岁,性别Man,现在时间为:2021-09-06 10:30:38
# 大家好,我的名字是小哈,今年18岁,性别Man,现在时间为:2021-09-06 10:31:08
# 大家好,我的名字是蓝精灵,今年1000岁,性别unknown,现在时间为:2021-09-06 10:31:08
# 大家好,我的名字是王铁锤,今年38岁,性别Woman,现在时间为:2021-09-06 10:31:30
# 大家好,我的名字是小哈,今年18岁,性别Man,现在时间为:2021-09-06 10:31:38
# 大家好,我的名字是科比,今年42岁,性别Man,现在时间为:2021-09-06 10:31:38
# 大家好,我的名字是小哈,今年18岁,性别Man,现在时间为:2021-09-06 10:32:08
# 大家好,我的名字是小哈,今年18岁,性别Man,现在时间为:2021-09-06 10:32:38
# 大家好,我的名字是科比,今年42岁,性别Man,现在时间为:2021-09-06 10:32:38
# 大家好,我的名字是蓝精灵,今年1000岁,性别unknown,现在时间为:2021-09-06 10:32:38
# 大家好,我的名字是王铁锤,今年38岁,性别Woman,现在时间为:2021-09-06 10:33:00

3、触发器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 (datetime 或 str)
最早开始日期(包含)
end_date (datetime 或 str)
最晚结束时间(包含)
timezone (datetime.tzinfo 或str)
指定时区
这些参数支持算数表达式,取值格式有如下:

图片.jpg

使用例子:
from apscheduler.schedulers.blocking import BlockingScheduler  # 定时任务
from JobStores import job

'''
三种模式:
(1)date: 特定的时间点触发,最基本的一种调度,作业只会执行一次。
(2)interval: 固定时间间隔触发(在某个时间范围内间隔多长时间执行一次)
(3)cron: 在特定时间周期性地触发(cron 和Linux crontab格式兼容,最为强大)
参数说明:
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 (datetime 或 str): 开始日期
end_date (datetime 或 str): 结束日期
timezone (datetime.tzinfo 或str): 时区
'''

scheduler = BlockingScheduler()

# xx:xx:30执行一次
# scheduler.add_job(job.hello, 'cron', second=30, args=['小哈'])
# 每30秒执行一次(计时起点取整)
# scheduler.add_job(job.hello, 'cron', second='*/30', args=['小呵'])

# 每分钟执行一次
scheduler.add_job(job.hello, 'cron', minute='*/1', args=['科比', 42])
# 在每天11和12点,每分钟执行一次
scheduler.add_job(job.hello, 'cron', hour='11-12', minute='*/1', args=['科比-布莱恩特', 42])
# 在每天11和12点,每10秒执行一次
scheduler.add_job(job.hello, 'cron', hour='11-12', second='*/10', args=['超级赛亚人', 928])
# 在每天11和12点的55和56分,每10秒执行一次
scheduler.add_job(job.hello, 'cron', hour='11-12', minute='55-56', second='*/10', args=['孙悟饭', 200])
# 在每周一的11和12点的55和56分,每10秒执行一次
scheduler.add_job(job.hello, 'cron', day_of_week='1', hour='11-12', minute='55-56', second='*/10',
                  args=['擎天柱', 129, 'unknown'])
# 在每周的周一到周五的11和12点的55和56分,每10秒执行一次
scheduler.add_job(job.hello, 'cron', day_of_week='1-5', hour='11-12', minute='55-56', second='*/10',
                  args=['威震天', 190, 'unknown'])
# 在每月的1号,11号,21号,31号的11和12点的55和56分,每10秒执行一次
scheduler.add_job(job.hello, 'cron', day='*/10', hour='11-12', minute='55-56', second='*/10',
                  args=['大黄蜂', 36, 'unknown'])
# 在每月的1-10号的周一到周五的11和12点的55和56分,每10秒执行一次
scheduler.add_job(job.hello, 'cron', day='1-10', day_of_week='1-5', hour='11-12', minute='55-56', second='*/10',
                  args=['霸天虎', 58, 'unknown'])

scheduler.start()

4、通过装饰器scheduled_job()添加方法

 添加任务的方法有两种:
(1)通过调用add_job()---见上面1至3代码
(2)通过装饰器scheduled_job():第一种方法是最常用的方法。第二种方法主要是方便地声明在应用程序运行时不会更改的任务。该 add_job()方法返回一个apscheduler.job.Job实例,可以使用该实例稍后修改或删除该任务。
使用例子:
import time
from apscheduler.schedulers.blocking import BlockingScheduler

scheduler = BlockingScheduler()

# 每五秒执行一次
@scheduler.scheduled_job('interval', seconds=5)
def job_one():
    t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    print(f'job_one --- {t}')

# 每七秒执行一次
@scheduler.scheduled_job('cron', second='*/7')
def job_two():
    t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    print(f'job_two --- {t}')


scheduler.start()

# job_two --- 2021-09-07 09:17:07
# job_one --- 2021-09-07 09:17:11
# job_two --- 2021-09-07 09:17:14
# job_one --- 2021-09-07 09:17:16

六、写在最后

入门使用就这些,更高深的用法在实践中去发现吧。。。
THE END
分享
二维码
打赏
< <上一篇
下一篇>>