一、介绍:
APScheduler的全称是Advanced Python Scheduler。它是一个轻量级的 Python 定时任务调度框架。
APScheduler 支持三种调度任务:固定时间间隔,固定时间点(日期),它还支持异步执行、后台执行调度任务。
这里只介绍如何执行调度任务
二、安装:
pip install apscheduler
三、基本概念
1. APScheduler四大组件:
触发器 triggers :用于设定触发任务的条件
任务储存器 job stores:用于存放任务,把任务存放在内存或数据库中
执行器 executors: 用于执行任务,可以设定执行模式为单线程或线程池
调度器 schedulers: 把上方三个组件作为参数,通过创建调度器实例来运行
1.1 触发器 triggers
触发器包含调度逻辑。每个任务都有自己的触发器,用于确定何时应该运行作业。除了初始配置之外,触发器完全是无状态的。
1.2 任务储存器 job stores
默认情况下,任务存放在内存中。也可以配置存放在不同类型的数据库中。如果任务存放在数据库中,那么任务的存取有一个序列化和反序列化的过程,同时修改和搜索任务的功能也是由任务储存器实现。
注意一个任务储存器不要共享给多个调度器,否则会导致状态混乱
1.3 执行器 executors
任务会被执行器放入线程池或进程池去执行,执行完毕后,执行器会通知调度器。
1.4 调度器 schedulers
一个调度器由上方三个组件构成,一般来说,一个程序只要有一个调度器就可以了。开发者也不必直接操作任务储存器、执行器以及触发器,因为调度器提供了统一的接口,通过调度器就可以操作组件,比如任务的增删改查
2. APScheduler有三种内置的触发器:
date 日期:触发任务运行的具体日期
interval 间隔:触发任务运行的时间间隔
cron 周期:触发任务运行的周期
calendarinterval:当您想要在一天中的特定时间以日历为基础的间隔运行任务时使用
一个任务也可以设定多种触发器,比如,可以设定同时满足所有触发器条件而触发,或者满足一项即触发。
2.1 date 是最基本的一种调度,作业任务只会执行一次。它表示特定的时间点触发。它的参数如下:
参数 说明
run_date(datetime or str) 任务运行的日期或者时间
timezone(datetime.tzinfo or str) 指定时区
代码:
from apscheduler.schedulers.blocking import BlockingScheduler
#创建执行的scheduler
scheduler = BlockingScheduler()
def works():
print(1111)
scheduler.add_job(works,'data',run_date=datetime.datetime(2020,12,4,15,54,0))#定时运行,只运行一次
scheduler.start()#启动scheduler
2.2 interval 周期触发任务
固定时间间隔触发。interval 间隔调度,参数如下:
参数 说明
weeks(int) 间隔几周
days(int) 间隔几天
hours(int) 间隔几小时
minutes(int) 间隔几分钟
seconds(int) 间隔多少秒
start_date(datetime or str) 开始日期
end_date(datetime or str) 结束日期
timezone(datetime.tzinfo or str) 时区
代码:
from apscheduler.schedulers.blocking import BlockingScheduler
#创建执行的scheduler
scheduler = BlockingScheduler()
def works():
print(1111)
#interval触发器,固定时间间隔触发,每两秒运行一次
scheduler.add_job(works, 'interval', seconds=2)
scheduler.start()#启动scheduler
2.3 cron 触发器
在特定时间周期性地触发,和Linux crontab格式兼容。它是功能最强大的触发器。
cron 参数:
参数 说明
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) 指定时区
代码:
from apscheduler.schedulers.blocking import BlockingScheduler
#创建后台执行的scheduler
scheduler = BlockingScheduler()
def works():
print(1111)
#interval触发器,固定时间间隔触发,每两秒运行一次
scheduler.add_job(works,'cron',day_of_week='1,3,6',hour='6',minute='30')
scheduler.start()#启动scheduler
四.注意事项
1.如果引用的其他脚本函数,需要将函数的包放置在任务函数包下
2.任务设置为interval或是cron等间隔时,第一次是不会执行的
3.如果使用的是BackgroundScheduler任务,那如果要执行子任务,那么主任务不能退出执行,
4.如果你是想在特定的小时(hour)执行任务,一定要设定好timezone参数,不然会有时差,会导致不会在特定的任务执行
查询本地时区
from tzlocal import get_localzone tz = get_localzone() print(tz)
五.个人配置
""" 管理全部的定时任务 使用框架:APScheduler """ import time import gc import json import requests from datetime import datetime import pandas as pd from sqlalchemy.dialects.mysql import MEDIUMINT,VARCHAR,DATETIME from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.blocking import BlockingScheduler # from apscheduler.jobstores.mongodb import MongoDBJobStore from apscheduler.jobstores.redis import RedisJobStore from apscheduler.jobstores.memory import MemoryJobStore from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor # 时间监听器 from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR import logging from java_interface import query_nickname, account_id_index from my_toolkit import chinese_check,sql_write_read,public_function LOGGNAME = 'scheduler.txt' logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filename=LOGGNAME, filemode='a') REDIS = { 'host': '127.0.0.1', 'port': '6379', 'db': 4, 'password': '', } def scheduler_listener(event): """事件监听器""" if event.exception: print(f'{event.job_id}:任务出错了!!!') else: print(f'{event.job_id}:任务照常运行,完成...') if __name__ == '__main__': # 触发器配置项:作业存储后台设置,执行器执行方式,调度器 jobstores = { 'redis': RedisJobStore(jobs_key='dispatched_jobs', run_times_key='dispatched_running',**REDIS), # 'default':MemoryJobStore() } executors = { 'default': ThreadPoolExecutor(10), 'processpool': ProcessPoolExecutor(5) } job_defaults = { 'coalesce': False, 'max_instances': 5 } scheduler = BackgroundScheduler(timezone='Asia/Shanghai', jobstores=jobstores, executors=executors, job_defaults=job_defaults) # 添加任务 scheduler.add_job(query_nickname.request_nickname, trigger='cron', jobstore='redis',id='query_nickname', hour='10', replace_existing=True) scheduler.add_job(account_id_index.station_id_index_from_api, trigger='cron',jobstore='redis', id='query_account_id_index', hour='10',replace_existing=True) # 添加事件监听器 scheduler.add_listener(scheduler_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR) # 添加日志 scheduler._logger = logging # 开始进程 scheduler.start() while 1: time.sleep(1000)
六、调度流程