APScheduler学习

Posted longweiqiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了APScheduler学习相关的知识,希望对你有一定的参考价值。

说明

APScheduler是一个 Python 定时任务框架,使用起来十分方便。提供了基于日期、固定时间间隔以及 crontab 类型的任务,并且可以持久化任务、并以 daemon 方式运行应用。
使用 APScheduler 需要安装
 

安装:

1 pip install apscheduler

 

首先来看一个周一到周五每天早上6点半喊我起床的例子:

1 from apscheduler.schedulers.blocking import BlockingScheduler
2 from datetime import datetime
3 # 输出时间
4 def job():
5     print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
6 # BlockingScheduler
7 scheduler = BlockingScheduler()
8 scheduler.add_job(job, cron, day_of_week=1-5, hour=6, minute=30)
9 scheduler.start()
代码中的 BlockingScheduler 是什么呢?
BlockingScheduler是APScheduler中的调度器,APScheduler 中有两种常用的调度器,BlockingScheduler 和 BackgroundScheduler,当调度器是应用中唯一要运行的任务时,使用 BlockingSchedule,如果希望调度器在后台执行,使用 BackgroundScheduler。
 

APScheduler四个组件

APScheduler 四个组件分别为:触发器(trigger),作业存储(job store),执行器(executor),调度器(scheduler)。

触发器(trigger)

 

包含调度逻辑,每一个作业有它自己的触发器,用于决定接下来哪一个作业会运行。除了他们自己初始配置意外,触发器完全是无状态的
APScheduler 有三种内建的 trigger:
  • date: 特定的时间点触发
  • interval: 固定时间间隔触发
  • cron: 在特定时间周期性地触发

 

作业存储(job store)

存储被调度的作业,默认的作业存储是简单地把作业保存在内存中,其他的作业存储是将作业保存在数据库中。一个作业的数据讲在保存在持久化作业存储时被序列化,并在加载时被反序列化。调度器不能分享同一个作业存储。
APScheduler 默认使用 MemoryJobStore,可以修改使用 DB 存储方案
 

执行器(executor)

处理作业的运行,他们通常通过在作业中提交制定的可调用对象到一个线程或者进城池来进行。当作业完成时,执行器将会通知调度器。
最常用的 executor 有两种:
  • ProcessPoolExecutor
  • ThreadPoolExecutor

 

调度器(scheduler)

通常在应用中只有一个调度器,应用的开发者通常不会直接处理作业存储、调度器和触发器,相反,调度器提供了处理这些的合适的接口。配置作业存储和执行器可以在调度器中完成,例如添加、修改和移除作业。

配置调度器

APScheduler提供了许多不同的方式来配置调度器,你可以使用一个配置字典或者作为参数关键字的方式传入。你也可以先创建调度器,再配置和添加作业,这样你可以在不同的环境中得到更大的灵活性。
下面来看一个简单的 BlockingScheduler 例子
 1 from apscheduler.schedulers.blocking import BlockingScheduler
 2 from datetime import datetime
 3 
 4 
 5 def job():
 6     print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
 7 # 定义BlockingScheduler
 8 sched = BlockingScheduler()
 9 sched.add_job(job, interval, seconds=5)
10 sched.start()
上述代码创建了一个 BlockingScheduler,并使用默认内存存储和默认执行器。(默认选项分别是 MemoryJobStore 和 ThreadPoolExecutor,其中线程池的最大线程数为10)。配置完成后使用 start() 方法来启动。
如果想要显式设置 job store(使用mongo存储)和 executor 可以这样写:
 1 from datetime import datetime
 2 from pymongo import MongoClient
 3 from apscheduler.schedulers.blocking import BlockingScheduler
 4 from apscheduler.jobstores.memory import MemoryJobStore
 5 from apscheduler.jobstores.mongodb import MongoDBJobStore
 6 from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
 7 # MongoDB 参数
 8 host = 127.0.0.1
 9 port = 27017
10 client = MongoClient(host, port)
11 # 输出时间
12 def job():
13     print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
14 # 存储方式
15 jobstores = {
16     mongo: MongoDBJobStore(collection=job, database=test, client=client),
17     default: MemoryJobStore()
18 }
19 executors = {
20     default: ThreadPoolExecutor(10),
21     processpool: ProcessPoolExecutor(3)
22 }
23 job_defaults = {
24     coalesce: False,
25     max_instances: 3
26 }
27 scheduler = BlockingScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults)
28 scheduler.add_job(job, interval, seconds=5, jobstore=mongo)
29 scheduler.start()
在运行程序5秒后,第一次输出时间。
在 MongoDB 中可以看到 job 的状态
技术图片

 

 

对 job 的操作

添加 job

添加job有两种方式:
  1. add_job()
  2. scheduled_job()
第二种方法只适用于应用运行期间不会改变的 job,而第一种方法返回一个apscheduler.job.Job 的实例,可以用来改变或者移除 job。
1 from apscheduler.schedulers.blocking import BlockingScheduler
2 sched = BlockingScheduler()
3 # 装饰器
4 @sched.scheduled_job(interval, id=my_job_id, seconds=5)
5 def job_function():
6     print("Hello World")
7 # 开始
8 sched.start()
@sched.scheduled_job() 是 Python 的装饰器。

 

移除 job

移除 job 也有两种方法:
  1. remove_job()
  2. job.remove() 
remove_job 使用 jobID 移除
job.remove() 使用 add_job() 返回的实例
1 job = scheduler.add_job(myfunc, interval, minutes=2)
2 job.remove()
3 # id
4 scheduler.add_job(myfunc, interval, minutes=2, id=my_job_id)
5 scheduler.remove_job(my_job_id)

 

暂停和恢复 job

暂停一个 job:
1 apscheduler.job.Job.pause()
2 apscheduler.schedulers.base.BaseScheduler.pause_job()

恢复一个 job:

1 apscheduler.job.Job.resume()
2 apscheduler.schedulers.base.BaseScheduler.resume_job()

希望你还记得 apscheduler.job.Job 是 add_job() 返回的实例

 

获取 job 列表

获得可调度 job 列表,可以使用get_jobs() 来完成,它会返回所有的 job 实例。
也可以使用print_jobs() 来输出所有格式化的 job 列表
  

修改 job

除了 jobID 之外 job 的所有属性都可以修改,使用 apscheduler.job.Job.modify() 或者 modify_job() 修改一个 job 的属性
1 job.modify(max_instances=6, name=Alternate name)
2 modify_job(my_job_id, trigger=cron, minute=*/5)

 

关闭 job

默认情况下调度器会等待所有的 job 完成后,关闭所有的调度器和作业存储。将 wait 选项设置为 False 可以立即关闭。
1 scheduler.shutdown()
2 scheduler.shutdown(wait=False)

 

scheduler 事件

scheduler 可以添加事件监听器,并在特殊的时间触发。
1 def my_listener(event):
2     if event.exception:
3         print(The job crashed :()
4     else:
5         print(The job worked :))
6 # 添加监听器
7 scheduler.add_listener(my_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)

 

trigger 规则

date

最基本的一种调度,作业只会执行一次。它的参数如下:
  • run_date (datetime|str) – the date/time to run the job at
  • timezone (datetime.tzinfo|str) – time zone for run_date if it doesn’t have one already
 1 from datetime import date
 2 from apscheduler.schedulers.blocking import BlockingScheduler
 3 sched = BlockingScheduler()
 4 def my_job(text):
 5     print(text)
 6 # The job will be executed on November 6th, 2009
 7 sched.add_job(my_job, date, run_date=date(2009, 11, 6), args=[text])
 8 sched.add_job(my_job, date, run_date=datetime(2009, 11, 6, 16, 30, 5), args=[text])
 9 sched.add_job(my_job, date, run_date=2009-11-06 16:30:05, args=[text])
10 # The ‘date‘ trigger and datetime.now() as run_date are implicit
11 sched.add_job(my_job, args=[text])
12 sched.start()

 

cron

  • 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)

中文释义:

参数
说明
(int|str)
表示参数既可以是int类型,也可以是str类型
(datetime | str)
表示参数既可以是datetime类型,也可以是str类型
year(int or str)
年,4位数字
month(int or str)
月(范围1-12)
day(int or str)
日(范围1-31)
week(int or str)
周(范围1-53)
day_of_week(int or str)
周内第几天或者星期几(范围0-6或者mon,tue,wed,thu,fri,stat,sun)
hour(int or str)
时(0-23)
minute(int or str)
分(0-59)
second(int or str)
秒(0-59)
start_date(datetime or str)
最早开始日期(含)
end_date(datetime or str)
最晚结束日期(含)
timezone(datetime.tzinfo or   str) 指定时区

表达式:

技术图片

 

 示例:

 1 from apscheduler.schedulers.blocking import BlockingScheduler
 2 
 3 
 4 def job_function():
 5     print("Hello World")
 6 # BlockingScheduler
 7 sched = BlockingScheduler()
 8 # Schedules job_function to be run on the third Friday
 9 # of June, July, August, November and December at 00:00, 01:00, 02:00 and 03:00
10 sched.add_job(job_function, cron, month=6-8,11-12, day=3rd fri, hour=0-3)
11 # Runs from Monday to Friday at 5:30 (am) until 2014-05-30 00:00:00
12 sched.add_job(job_function, cron, day_of_week=mon-fri, hour=5, minute=30, end_date=2014-05-30)
13 sched.start()

 

interval

参数:
  • weeks (int) – number of weeks to wait
  • days (int) – number of days to wait
  • hours (int) – number of hours to wait
  • minutes (int) – number of minutes to wait
  • seconds (int) – number of seconds to wait
  • start_date (datetime|str) – starting point for the interval calculation
  • end_date (datetime|str) – latest possible date/time to trigger on
  • timezone (datetime.tzinfo|str) – time zone to use for the date/time calculations
示例:
 1 from datetime import datetime
 2 from apscheduler.schedulers.blocking import BlockingScheduler
 3 
 4 
 5 def job_function():
 6     print("Hello World")
 7 # BlockingScheduler
 8 sched = BlockingScheduler()
 9 # Schedule job_function to be called every two hours
10 sched.add_job(job_function, interval, hours=2)
11 # The same as before, but starts on 2010-10-10 at 9:30 and stops on 2014-06-15 at 11:00
12 sched.add_job(job_function, interval, hours=2, start_date=2010-10-10 09:30:00, end_date=2014-06-15 11:00:00)
13 sched.start()

 

踩坑记录:

1、cron编写场景为每周五上午十点执行一次时,day_of_week字段为4,即当前星期数-1,也可以写成‘fri‘

 

文章来源:

 
 
 
 
 
 

以上是关于APScheduler学习的主要内容,如果未能解决你的问题,请参考以下文章

定时任务框架APScheduler学习详解

定时任务框架APScheduler学习详解

Flask 学习-87.Flask-APScheduler 持久化定时任务保存到mysql数据库

Python定时任务框架APScheduler快速入门

Django-Apscheduler 定时任务

RuntimeError:异步+ apscheduler中的线程中没有当前事件循环