目录
简介:
官网地址:Advanced Python Scheduler — APScheduler 3.8.1.post1 documentation
APScheduler具有四种组件:
-
触发器 triggers
-
作业 job stores
-
执行器 executors
-
调度器 schedulers
调度器:
调度程序的选择主要取决于您的编程环境以及APScheduler的用途。这是选择调度程序的快速指南:
-
BlockingScheduler:当调度程序是您的流程中唯一运行的东西时使用
-
BackgroundScheduler:在不使用以下任何框架且希望调度程序在应用程序内部的后台运行时使用
-
AsyncIOScheduler:如果您的应用程序使用asyncio模块,则使用
-
GeventScheduler:如果您的应用程序使用gevent,则使用
-
TornadoScheduler:在构建Tornado应用程序时使用
-
TwistedScheduler:在构建Twisted应用程序时使用
-
QtScheduler
:在构建Qt应用程序时使用
APScheduler具有三个可以使用的内置调度系统:
-
Cron样式的排程(具有可选的开始/结束时间)
-
基于间隔的执行(以偶数间隔运行作业,并具有可选的开始/结束时间)
-
一次性延迟执行(在设定的日期/时间运行一次作业)
触发器
APScheduler带有三种内置的触发器类型:
add_job(): interval 固定时间间隔触发
apscheduler.triggers.interval — APScheduler 3.8.1.post1 documentation
Parameters
-
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
-
jitter (int|None) – delay the job execution by
jitter
seconds at most
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
def job_function():
print("Hello World")
sched = BlockingScheduler()
# Schedule job_function to be called every two hours
sched.add_job(job_function, 'interval', hours=2)
sched.start()
add_job(): cron 指定时间间隔触发
apscheduler.triggers.cron — APScheduler 3.8.1.post1 documentation
Parameters
-
year (int|str) – 4-digit year
-
month (int|str) – month (1-12)
-
day (int|str) – day of month (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)
-
jitter (int|None) – delay the job execution by
jitter
seconds at most
from apscheduler.schedulers.blocking import BlockingScheduler
def job_function():
print "Hello World"
sched = BlockingScheduler()
# Schedules job_function to be run on the third Friday
# of June, July, August, November and December at 00:00, 01:00, 02:00 and 03:00
sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
sched.start()
add_job(): date 指定时间仅运行一次
apscheduler.triggers.date — APScheduler 3.8.1.post1 documentation
Parameters
-
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
from datetime import date
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
def my_job(text):
print(text)
# The job will be executed on November 6th, 2009
sched.add_job(my_job, 'date', run_date=date(2009, 11, 6), args=['text'])
# The job will be executed on November 6th, 2009 at 16:30:05
sched.add_job(my_job, 'date', run_date=datetime(2009, 11, 6, 16, 30, 5), args=['text'])
sched.start()
实例封装
# -*- coding: utf-8 -*-
# @Time: 2021/12/2 13:57
"""
定时器
调度器开启后,可以添加多个任务
"""
import time
from apscheduler.events import *
from apscheduler.executors.pool import ProcessPoolExecutor, ThreadPoolExecutor
from pytz import utc
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
class TimeScheduler:
scheduler = None
def __init__(self):
if not self.scheduler:
# self.scheduler = BlockingScheduler() # 当调度程序是你的进程中唯一运行的东西时使用
self.scheduler = BackgroundScheduler() # 希望调度程序在您的应用程序内的后台运行,默认最大线程数为 10
# self.scheduler = SQLAlchemyJobStore() # 使用 SQLAlchemy 将作业存储在数据库表中。如果数据库中不存在该表,则将创建该表。
def start_scheduler(self):
"""
开启调度器
:return:
"""
if self.scheduler_status() == 0:
self.scheduler.start()
def shutdown_scheduler(self, wait=True):
"""
关闭调度器,这会关闭所有任务, 默认等待正在进行的任务完成
:return:
"""
self.scheduler.shutdown(wait=wait)
def scheduler_status(self):
"""
返回定时任务状态 0:已停止,1:运行中,2:暂停中
:return: int 类型状态
"""
if self.scheduler:
return self.scheduler.state
else:
return 0
def add_config(self, jobstores=None, executors=None, job_defaults=None, timezone=None):
"""
UTC 作为调度程序的时区, 默认情况下为新作业关闭合并, 新作业的默认最大实例限制为 3
:param jobstores: 作业存储配置
:param executors: 执行器配置
:param job_defaults: 定时任务配置
:param timezone: 时区配置
:return:
"""
if job_defaults is None:
job_defaults = {"coalesce": False, "max_instances": 3}
if executors is None:
executors = {'default': ThreadPoolExecutor(20), 'processpool': ProcessPoolExecutor(max_workers=5)}
if jobstores is None:
jobstores = {'mongo': {'type': 'mongodb'}, 'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')}
if timezone is None:
timezone = utc
self.scheduler.configure(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=timezone)
def add_interval_scheduler(self, job, job_id, days=1, hours=0, minutes=0, seconds=0,
start_date="", end_date=""):
"""
固定时间间隔执行,每隔一段时间执行一次
:param job: 执行方法
:param days: 第几天
:param hours: 小时
:param minutes: 分钟
:param seconds: 秒
:param start_date: 开始时间
:param end_date: 结束时间
:return:
"""
self.scheduler.add_job(func=job, trigger='interval', days=days, hours=hours, minutes=minutes,
seconds=seconds, start_date=start_date, end_date=end_date, id=job_id, max_instances=1)
def add_date_scheduler(self, job, job_id, run_date=""):
"""
指定时间仅执行一次
:param job: 执行方法
:param run_date: 执行时间
:return:
"""
self.scheduler.add_job(func=job, trigger='date', run_date=run_date, id=job_id, max_instances=1)
def add_cron_scheduler(self, job, job_id, day_of_week="0-6", hour=0, minute=0, second=0,
start_date="", end_date=""):
"""
一定时间周期内循环执行
:param job: 执行方法
:param day_of_week: 每周的第几天,默认每天
:param hour: 小时, 默认为0点
:param minute: 分钟,默认为0分
:param second: 秒, 默认为0秒
:param start_date: 开始时间, 默认为空
:param end_date: 结束时间, 默认为空
:return:
"""
self.scheduler.add_job(func=job, trigger='cron', day_of_week=day_of_week, hour=hour, minute=minute,
second=second, start_date=start_date, end_date=end_date, id=job_id, max_instances=1)
def get_jobs(self, job_id=None):
"""
获取当前定时任务
:param job_id: 默认获取全部任务,传入任务id时仅返回对应任务信息
:return: 全部/指定任务信息
"""
if job_id:
return self.scheduler.get_job(job_id=job_id)
else:
return self.scheduler.get_jobs()
def get_jobs_info(self, job_id=None):
"""
定时任务信息列表
:param job_id: 定时任务id ,默认为None 输出全部任务信息
:return: 任务信息列表
"""
jobs_info = []
# 判断是否要返回全部任务信息
if job_id is None:
# 判断当前是否有定时任务
if len(self.get_jobs()) == 0:
return jobs_info
else:
for job in self.get_jobs():
jobs_info.append((job.name, job.id, job.trigger, job.next_run_time, job.args, job.kwargs))
else:
job = self.get_jobs(job_id)
jobs_info.append((job.name, job.id, job.trigger, job.next_run_time, job.args, job.kwargs))
return jobs_info
def remove_jobs(self, job_id=None):
"""
在任务开始前移除任务
:param job_id: 任务id
:return:
"""
# 删除全部未在执行中的任务
if job_id is None:
for job in self.get_jobs():
if not self.get_jobs(job.id).pending:
self.scheduler.remove_job(job_id=job.id)
# 删除指定的未在执行中的任务
else:
if not self.get_jobs(job_id).pending:
self.scheduler.remove_job(job_id=job_id)
def pause_task(self, job_id=None):
"""暂停定时任务,默认暂停全部任务,否则暂停指定 job_id 的任务"""
if job_id is None:
self.scheduler.pause()
else: # 两种方式
# self.get_jobs(job_id).pause()
self.scheduler.pause_job(job_id)
def resume_task(self, job_id=None):
"""恢复暂停中的任务,默认恢复全部任务,否则恢复指定 job_id 的任务"""
if job_id is None:
self.scheduler.resume()
else:
if self.get_jobs(job_id):
self.get_jobs(job_id).resume()
def get_scheduler_status(self, event):
"""调度器事件:1:启动; 2:关闭; """
if event:
print("调度器事件:", event.code)
def get_task_status(self, event):
if event:
print("任务执行状态:", event.code)
def get_task_status_end(self, event):
if event:
# print(event.traceback)
print("任务结果----:", event.code)
def add_scheduler_listener(self):
"""添加调度器状态监听器"""
self.scheduler.add_listener(self.get_scheduler_status,
EVENT_SCHEDULER_STARTED | EVENT_SCHEDULER_SHUTDOWN | EVENT_SCHEDULER_PAUSED | EVENT_SCHEDULER_RESUMED)
def add_task_listener(self):
"""任务执行状态监听(不包含成功 失败)"""
self.scheduler.add_listener(self.get_task_status,
EVENT_JOBSTORE_ADDED | EVENT_JOBSTORE_REMOVED | EVENT_ALL_JOBS_REMOVED |
EVENT_JOB_ADDED | EVENT_JOB_REMOVED | EVENT_JOB_MODIFIED | EVENT_JOB_SUBMITTED |
EVENT_JOB_MAX_INSTANCES | EVENT_JOB_MISSED)
def add_task_end_listener(self):
"""任务执行成功 失败监听"""
self.scheduler.add_listener(self.get_task_status_end, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
def get_one():
print("--------get one-------------")
def get_two():
print("--------get two---------")
if __name__ == '__main__':
import datetime
t = TimeScheduler()
t.add_scheduler_listener()
# t.add_task_listener()
t.add_task_end_listener()
print("初始调度器状态:", t.scheduler_status())
t.start_scheduler()
print(t.get_jobs())
time_run = datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(seconds=3), "%Y-%m-%d %H:%M:%S")
t.add_date_scheduler(job=get_one, job_id="get----one", run_date=time_run)
t.add_date_scheduler(job=get_two, job_id="get----two", run_date=time_run)
print(t.get_jobs())
t_1 = t.get_jobs()[0]
print("任务是否进行中", t_1.pending)
print(t.get_jobs_info(t_1.id))
print(t_1.trigger)
time.sleep(5)
t.shutdown_scheduler()