【Python】APScheduler定时调度库

news2024/12/28 17:49:37

文章目录

    • APScheduler是什么
    • 功能特点
    • 四大组件
      • 触发器[triggers]
        • date 一次性触发器
        • interval 间隔触发器
        • cron 周期触发器
      • 任务存储器[JobStore]
        • MemoryJobStore
        • MongoDBJobStore
        • RedisJobStore
          • 示例代码
        • RethinkDBJobStore
        • SQLAlchemyJobStore
        • ZooKeeperJobStore
      • 执行器[executors]
        • 线程池执行器[ThreadPoolExecutor]
        • 进程池执行器[ProcessPoolExecutor]
        • Gevent程序执行器[GeventExecutor]
        • Tornado程序执行器[TornadoExecutor]
        • Twisted程序执行器[TwistedExecutor]
        • asyncio程序执行器[AsyncIOExecutor]
      • 调度器[schedulers]
        • 阻塞式调度器[BlockingScheduler]
        • 后台调度器[BackgroundScheduler]
        • AsyncIO调度器[AsyncIOScheduler]
        • Gevent调度器[GeventScheduler]
        • Tornado调度器[TornadoScheduler]
        • Twisted调度器[TwistedScheduler]
        • Qt调度器[QtScheduler]
    • 任务操作
      • 添加任务一[add_job()]
      • 添加任务二[scheduled_job()]
      • 移除job任务[remove_job()与job.remove()]
      • 暂停/恢复job任务[pause_job()/resume()]
      • 获取job列表[get_jobs()]
      • 修改job[modify()]
      • 开启job[start()]
      • 关闭job[shutdown()]
      • 给调度器绑定监视器[add_listener()]
    • 调度配置
      • jobstores 用来配置存储器
      • executors 用来配置执行器
      • job_defaults 创建job时的默认参数
      • 示例

APScheduler是什么

APScheduler库提供了强大而灵活的任务调度功能,支持多种调度方式、持久化存储和分布式任务调度等特性,适用于各种复杂任务调度的需求。

pip install apscheduler

功能特点

  • 多种调度方式:APScheduler支持多种调度方式,包括定时调度、间隔调度、日期调度等。可以根据需求选择适合的调度方式来执行任务。
  • 多线程支持:APScheduler是多线程的,可以同时执行多个任务,不会阻塞其他任务的执行。这使得它适合处理大量任务并提高任务执行效率。
  • 持久化存储:APScheduler支持将任务调度信息存储到数据库中,以保证任务调度信息的持久性。在应用程序重启后,可以从数据库中恢复任务调度状态,避免任务丢失。
  • 分布式任务调度:APScheduler支持分布式任务调度,可以在多台计算机上运行调度器,并使用分布式存储来共享任务调度信息。这使得任务可以在多个节点上协同执行,提高系统的可伸缩性和容错性。
  • 任务触发器:APScheduler提供了灵活的任务触发器,可以根据各种条件来触发任务执行,例如日期、时间间隔、定时表达式、CRON表达式等。这允许用户更精细地控制任务的执行时机。
  • 监听器和钩子:APScheduler支持任务监听器和钩子,可以在任务执行前后执行自定义的操作。这使得用户可以在任务执行过程中添加额外的逻辑,例如日志记录、错误处理等。

四大组件

触发器[triggers]

用于设定触发任务的条件

date 一次性触发器

作业任务只会执行一次。它表示特定的时间点触发。

参数说明
run_date (datetime 或 str)作业的运行日期或时间
timezone (datetime.tzinfo 或 str)指定时区

示例

# 在2023年4月15日执行
scheduler.add_job(my_job, 'date', run_date=date(2023, 4, 15), args=['测试任务'])


# datetime类型(用于精确时间)
scheduler.add_job(my_job, 'date', run_date=datetime(2023, 4, 15, 17, 30, 5), args=['测试任务'])

interval 间隔触发器

固定时间间隔触发

参数说明
weeks (int)间隔几周
days (int)间隔几天
hours (int)间隔几小时
minutes (int)间隔几分钟
seconds (int)间隔多少秒
start_date (datetime 或 str)开始日期
end_date (datetime 或 str)结束日期
timezone (datetime.tzinfo 或str)时区
jitter触发的时间误差

示例

# 每2小时触发
scheduler.add_job(job_func, 'interval', hours=2)
 
# 在 2023-04-15 17:00:00 ~ 2023-12-31 24:00:00 之间, 每隔两分钟执行一次 job_func 方法
scheduler.add_job(job_func, 'interval', minutes=2, start_date='2023-04-15 17:00:00' , end_date='2023-12-31 24:00:00')

cron 周期触发器

在特定时间周期性地触发,和Linux crontab格式兼容。它是功能最强大的触发器。

参数说明
year (int 或 str)年,4位数字
month (int 或 str)月 (范围1-12或jan–dec)
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)指定时区
jitter任务触发的误差时间
表达式参数类型描述
*所有通配符。例:minutes=*即每分钟触发
*/a所有可被a整除的通配符。
a-b所有范围a-b触发
a-b/c所有范围a-b,且可被c整除时触发
xth y [day]第x个星期y触发
last x [day]一个月中,最后一个星期x触发
last [day]一个月最后一天触发
x,y,z所有组合表达式,可以组合确定值或上方的表达式

示例

# 在每年 1-3、7-9 月份中的每个星期一、二中的 00:00, 01:00, 02:00 和 03:00 执行 job_func 任务
scheduler.add_job(job_func, 'cron', month='1-3,7-9',day='0, tue', hour='0-3')

任务存储器[JobStore]

用于存放任务,把任务存放在内存或数据库中

持久化存储

默认是把任务保存在内存中,持久化是将任务保存在数据库中。

一个任务的数据将在保存在持久化的任务存储之前,会对任务执行序列化操作,当重新读取任务时,再执行反序列化操作。(下面第二部分代码就是用的redis存储)

MemoryJobStore

# 没有序列化,任务存储在内存中,增删改查都在内存中完成
from apscheduler.jobstores.memory import MemoryJobStore

MongoDBJobStore

# 使用mongodb作为存储器
from apscheduler.jobstores.mongodb import MongoDBJobStore

RedisJobStore

# 使用redis作为存储器
from apscheduler.jobstores.redis import RedisJobStore
示例代码
from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask, make_response
 
app = Flask(__name__)

jobstores = {
    # 用redis作backend
    'redis': RedisJobStore(),
}
executors = {
    'default': ThreadPoolExecutor(10),#默认线程数
    'processpool': ProcessPoolExecutor(3)#默认进程
}
conf = {
        "host": "127.0.0.1",
        "port": 6379,
        "db": 0,
        "max_connections": 10
      }
job_defaults = {
        'coalesce': False,
        'max_instances': 3
        }
# coalesce:累计的 任务是否执行。True不执行,False,执行。
# 同上,由于某种原因,比如进场挂了,导致任务多次没有调用,则前几次的累计任务的任务是否执行的策略。
# max_instances:同一个任务在线程池中最多跑的实例数。
def my_job():
    print('定时任务')
 
sched = BackgroundScheduler(timezone='MST', jobstores=jobstores, executors=executors)
# 添加redis为作业存储
sched.add_jobstore(jobstore="redis", **conf)
sched.add_job(my_job, 'interval', id='3_second_job', seconds=3,misfire_grace_time=60)
# misfire_grace_time:超过用户设定的时间范围外,该任务依旧执行的时间(单位时间s)。比如用户设置#misfire_grace_time=60,于12:00触发任务。由于某种原因在12:00没有触发,被延时了。如果时间在12:01内,该任务仍能触发,超过3:01任务不执行
 
@app.route('/start')
def ds():
    sched.start()
    sched.remove_job('3_second_job')  # 删除任务
    sched.pause()  # 暂定任务
    sched.resume()  # 恢复任务
    return 'ok'


@app.route('/ssst')
def st():
    sched.start()
    return 'ok'

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)

RethinkDBJobStore

SQLAlchemyJobStore

# 使用SQLAlchemy这个ORM框架作为存储方式
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore

ZooKeeperJobStore

执行器[executors]

用于执行任务,可以设定执行模式为单线程或线程池

线程池执行器[ThreadPoolExecutor]

默认执行器

from apscheduler.executors.pool import ThreadPoolExecutor

进程池执行器[ProcessPoolExecutor]

适用于涉及到一些CPU密集计算的操作

from apscheduler.executors.pool import ProcessPoolExecutor

Gevent程序执行器[GeventExecutor]

from apscheduler.executors.gevent import GeventExecutor

Tornado程序执行器[TornadoExecutor]

from apscheduler.executors.tornado import TornadoExecutor

Twisted程序执行器[TwistedExecutor]

from apscheduler.executors.twisted import TwistedExecutor

asyncio程序执行器[AsyncIOExecutor]

from apscheduler.executors.asyncio import AsyncIOExecutor

调度器[schedulers]

把上方三个组件作为参数,通过创建调度器实例来运行

阻塞式调度器[BlockingScheduler]

阻塞式调度器:适用于只跑调度器的程序。

调用start函数会阻塞当前线程,不能立即返回。适用于调度程序时进程中唯一运行的进程

from apscheduler.schedulers.blocking import BlockingScheduler

后台调度器[BackgroundScheduler]

适用于非阻塞的情况,调度器会在后台独立运行。

from apscheduler.schedulers.background import BackgroundScheduler

AsyncIO调度器[AsyncIOScheduler]

适用于应用使用AsnycIO的情况。

from apscheduler.schedulers.asyncio import AsyncIOScheduler

Gevent调度器[GeventScheduler]

适用于应用通过Gevent的情况。

from apscheduler.schedulers.gevent import GeventScheduler

Tornado调度器[TornadoScheduler]

适用于构建Tornado应用。

from apscheduler.schedulers.tornado import TornadoScheduler

Twisted调度器[TwistedScheduler]

适用于构建Twisted应用。

from apscheduler.schedulers.twisted import TwistedScheduler

Qt调度器[QtScheduler]

适用于构建Qt应用。

from apscheduler.schedulers.qt import QtScheduler

任务操作

添加任务一[add_job()]

返回一个 apscheduler.job.Job 的实例,可以用来改变或者移除job。

如果调度的job在一个持久化的存储器里,当初始化应用程序时,必须要为job定义一个显示的ID并使用replace_existing=True, 否则每次应用程序重启时都会得到那个job的一个新副本

import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
 
scheduler = BlockingScheduler()
 
def my_job(text):
    print(text)
    
# datetime类型(用于精确时间)
scheduler.add_job(my_job, 'date', run_date=datetime(2023, 4, 15, 17, 30, 5), args=['测试任务'])
 
scheduler.start()

添加任务二[scheduled_job()]

只适用于应用运行期间不会改变的job。

import datetime
from apscheduler.schedulers.background import BackgroundScheduler
 
@scheduler.scheduled_job(job_func, 'interval', minutes=2)
def job_func(text):
    print(datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3])
 
scheduler = BackgroundScheduler()
scheduler.start()

移除job任务[remove_job()与job.remove()]

  • remove_job() 是根据job的id来移除,所以要在job创建的时候指定一个id。
  • job.remove() 则是对job执行remove方法即可
  • remove_all_jobs() 对scheduler所有任务进行移除
scheduler = BlockingScheduler()

scheduler.add_job(job_func, 'interval', minutes=2, id='job_one')
scheduler.remove_job(job_id="job_one")

# 添加任务并获取Job对象
job = add_job(job_func, 'interval', minutes=2, id='job_one')
# 移除特定的任务
job.remvoe()

# 移除所有的任务
scheduler.remove_all_jobs()

暂停/恢复job任务[pause_job()/resume()]

  • 通过job实例

    # 暂停job任务
    job = scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_remove")
    job.pause()
    
    # 恢复job任务
    job = scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_remove")
    job.resume()
    
  • 通过schedule本身

    # 暂停job任务
    scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_remove")
    scheduler.pause_job(job_id="job_remove")
    
    # 恢复job任务
    scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_remove")
    scheduler.resume_job(job_id="job_remove")
    

获取job列表[get_jobs()]

获取当前调度器中的所有 job 的列表,返回一个Job实例列表

修改job[modify()]

Job.modify() 或者 modify_job()方法来修改 job 的属性。但是值得注意的是,job 的 id 是无法被修改的。

# 通过实例修改
job = scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_modify")
job.modify(name="job222")

# 通过job的ID进行修改
scheduler.add_job(my_job, 'interval', minutes=10, id='one')
scheduler.start()
# 将触发时间间隔修改成 5分钟
scheduler.modify_job(job_id='one', minutes=5)

reschedule()、reschedule_job()通过重启调度的方式,对job进行修改

job = scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_modify")

# reschedule
job.reschedule(trigger='cron', minute='*/5')
# reschedule_job
scheduler.reschedule_job(job_id="job_modify", trigger='cron', minute='*/5')

开启job[start()]

scheduler.start(paused=True)

# 如果没有进行过唤醒,也可以对处于暂停状态的调度器执行start操作

关闭job[shutdown()]

默认情况下调度器会等待所有正在运行的作业完成后,关闭所有的调度器和作业存储。如果你不想等待,可以将 wait 选项设置为 False。

scheduler.shutdown()
scheduler.shutdown(wait=false)

给调度器绑定监视器[add_listener()]

def my_listener(event):
    if event.exception:
        print("任务出错了!!!!!!!!!")
    else:
        print("任务正常运行。。。。。")
# 绑定事件监听器,当出现异常或者错误的时,进行监听
scheduler.add_listener(my_listener, mask=EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)

调度配置

jobstores 用来配置存储器

jobstores = {
    # 用redis作backend
    'redis': RedisJobStore(),
}

executors 用来配置执行器

executors = {
    'default': ThreadPoolExecutor(10),  # 默认线程数
    'processpool': ProcessPoolExecutor(3)  # 默认进程
}

job_defaults 创建job时的默认参数

job_defaults = {
    'coalesce': False,
    'max_instances': 3
}

'''
coalesce 是否合并执行
    比如由于某个原因导致某个任务积攒了很多次没有执行(比如有一个任务是1分钟跑一次,但是系统原因断了5分钟)
    如果 coalesce=True,那么下次恢复运行的时候,会只执行一次,
    而如果设置 coalesce=False,那么就不会合并,会5次全部执行。
max_instances 最大实例数
    同一个任务同一时间最多只能有n个实例在运行
'''

示例

from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor
 
interval_task = {
    # 配置存储器
    "jobstores": {
        # 使用SQLAlchemy进行存储,会自动创建数据库,并创建apscheduler_jobs表
        'default': SQLAlchemyJobStore(url="sqlite:///jobs.db")
    },
    # 配置执行器
    "executors": {
        # 使用线程池进行执行,最大线程数是20个
        'default': ThreadPoolExecutor(20)
    },
    # 创建job时的默认参数
    "job_defaults": {
        'coalesce': False,  # 是否合并执行
        'max_instances': 3  # 最大实例数
    }
 
}
scheduler = BlockingScheduler(**interval_task)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/660935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python如何隐藏进程

Python如何隐藏进程 介绍 进程是指运行中的程序在操作系统中的一个实例。在计算机系统中,进程通常都可以被用户或者其他程序所看到。然而,有时候我们需要隐藏进程,比如保护敏感信息或者防止恶意攻击。 Python是一种高级编程语言&#xff0…

Maven学习笔记(SSM 整合伪分布式案例)

目录 第一节 创建工程,引入依赖 1 创建工程 ①工程清单 ②工程间关系 2、各工程 POM 配置 ①父工程 ②Mybatis 逆向工程 ③环境依赖工程 ④工具类工程 ⑤实体类工程 ⑥组件工程 ⑦Web 工程 第二节 搭建环境:持久化层 1、物理建模 2、Myba…

leetcode算法 -- 数组

1 数组 常见的数组算法有双指针,滑动窗口,二分查找和分冶。 2 双指针 核心的思路:使用两个指针,一个从头开始索引,一个从尾开始索引。 2.1 两数之和ii 167 给你一个下标从 1 开始的整数数组 numbers ,该…

chatgpt赋能python:Python怎么随机生成一个数

Python怎么随机生成一个数 在Python编程中,经常有需要随机生成一个整数的需求,比如在游戏中生成随机的道具,或者在数据分析中进行随机采样。 Python中提供了一个内置的random模块,可以方便地实现随机生成一个数。 使用random模…

【Windows】虚拟串口工具VSPD6.9安装

【Windows】虚拟串口工具VSPD6.9安装 1、背景2、安装3、补丁4、验证5、下载 1、背景 参考【Windows】虚拟串口工具VSPD7.2安装。 本博客安装的版本是VSPD6.9,并在文末留下下载链接,以供学习研究。 虚拟串口工具一般用来做上位机软件的串口通信调试&…

Java性能权威指南-总结14

Java性能权威指南-总结14 堆内存最佳实践对象生命周期管理对象重用 堆内存最佳实践 对象生命周期管理 在很大程度上,Java会尽量减轻开发者投入到对象生命周期管理上的精力:开发者在需要的时候创建对象,当不再需要这些对象时,它们…

C++11新特性之右值引用

目录 前文 一,什么是右值引用? 二,左值引用和右值引用比较 三,右值引用的应用场景以及作用 四, 右值引用左值的场景分析 五,完美转发 总结 前文 在C98标准后,C11标准的更新为C注入了新活力&…

chatgpt赋能python:Python如何生成100个随机整数

Python如何生成100个随机整数 在Python中,我们可以使用random库来生成随机整数。在本文中,我们将介绍如何使用Python生成100个随机整数。 什么是随机整数 随机整数是指在一定范围内,产生的整数是随机的且不重复的。这在数据分析、机器学习…

2. CSS的元素显示模式

了解元素的显示模式可以更好的让我们布局页面. 1.什么是元素的显示模式 2.元素显示模式的分类 3.元素显示模式的转换 2.1什么是元素显示模式 作用:网页的标签非常多,在不同地方会用到不同类型的标签,了解他们的特点可以更好的布局我们的网页。 元素显示…

chatgpt赋能python:如何在Python中创建模块:完整指南

如何在Python中创建模块:完整指南 如果你是一位Python开发者,你肯定需要用到模块。模块使得代码更容易组织和管理,并且可以复用许多代码片段, 提高代码的可重用性。在Python中,模块是一组相关函数,方法和变…

[论文笔记]End-to-end Sequence Labeling via Bi-directional LSTM-CNNs-CRF

引言 本文是论文End-to-end Sequence Labeling via Bi-directional LSTM-CNNs-CRF的阅读笔记。 本论文提出了一个受益于单词级(word)和字符级(character)表示的网络架构,通过组合双向LSTM,CNN和CRF。 简介 首先通过CNN编码一个单词的字符级信息到相应的字符表征。然后组合…

【C数据结构】动态顺序表_SeqList

目录 【1】数据结构概述 【1.1】什么是数据结构? 【1.2】数据结构分类 【1.3】数据结构术语 【2】数据结构特点 【2】动态顺序表 【2.1】动态顺序表定义数据结构和接口 【2.1】动态顺序表创建初始化 【2.2】动态顺序表初始化 【2.3】动态顺序表内存释放 【…

【Express.js】处理请求数据

处理请求数据 本节将具体介绍express后端处理请求源携带数据的一些方法和技巧 动态路径 很多时候我们需要处理一些类似但有操作差别或不同对象的业务,我们可以监听一段基本路径,将其中某一个段或者某几段路径作为变量,在接口中根据不同的路…

大学计算机专业实习心得报告13篇

大学计算机专业实习心得报告(篇1) 通过理论联系实际,巩固所学的知识,提高处理实际问题的能力,为顺利毕业进行做好充分的准备,并为自己能顺利与社会环境接轨做准备。通过这次实习,使我们进一步理…

chatgpt赋能python:如何用Python创建优秀的项目

如何用Python创建优秀的项目 Python是一种功能强大的编程语言,可用于创建各种不同类型的项目。本文将介绍如何使用Python创建优秀的项目,并包括一些有用的技巧和工具。在本文中,我们将着重讨论如何优化我们的Python项目以获得更好的SEO排名。…

Gitlab 服务器搭建

引言 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。Gitlab是被广泛使用的基于git的开源代码管理平台, 基于Ruby on Rails构建, 主要针对软件开发过程中…

C语言:求输入的两个数的最小公倍数

题目: 求输入的两个数的最小公倍数 思路一:普通方法 (思路简单,效率较低) 总体思路: (一). 输入两个数:a 和 b, 使用 三目表达式 把较大值 取出 &#xff…

[元带你学: eMMC协议详解 17] eMMC 安全方案 之 RPMB(Replay Protected Memory Block 重放保护内存块)

依JEDEC eMMC 5.1及经验辛苦整理,付费内容,禁止转载。 所在专栏 《元带你学: eMMC协议详解》 内容摘要 全文 6300 字, 主要内容有 目录 1 概念 2 容量大小 3 重放保护的原理 4 不同访问类型流程 4.1. 写认证密钥(write Au…

coder oss 真正私有化部署的云端开发环境,nas也可以装

先看效果: 主界面,显示了你有那些工作空间 某个工作空间,我这里集成了web版vscode,也可以使用本地的vscode和其他开发IDE 有独立的终端和集成webide 以后就可以一个ipad都可以写代码了; 下面是平台搭建过程&#xff0…

C语言入门基础知识(万字笔记)

一、前言部分 本篇文章,将会主要介绍c语言的基本数据类型、基本运算符、语句,三大结构、数组、指针、宏定义等内容 二、具体部分 1、基本数据类型 1、基本数据类型 在C语言中,承载一系列信息的数字或中字符都属于数据类型,计算…