1. 简介与安装

​ Apscheduler是一个轻量级的 Python 定时任务调度框架。APScheduler 支持三种调度任务:固定时间间隔,固定时间点(日期),Linux 下的 Crontab 命令。同时,它还支持异步执行、后台执行调度任务。

pip install apscheduler

2. APScheduler基础组成

2.1 调度器(scheduler)
  • BlockingScheduler: 调度器在当前进程的主线程中运行,会阻塞当前线程。
  • BackgroundScheduler: 调度器在后台线程中运行,不会阻塞当前线程。
  • AsyncIOScheduler: 结合asyncio模块一起使用。
  • GeventScheduler: 程序中使用gevent作为IO模型和GeventExecutor配合使用。
  • TornadoScheduler: 程序中使用Tornado的IO模型,用 ioloop.add_timeout 完成定时唤醒。
  • TwistedScheduler: 配合TwistedExecutor,用reactor.callLater完成定时唤醒。
  • QtScheduler: 应用是一个Qt应用,需使用QTimer完成定时唤醒。
2.2 触发器(trigger)
  • date是最基本的一种调度,作业任务只会执行一次。参数详见
  • interval触发器,固定时间间隔触发。参数详见
  • cron 触发器,在特定时间周期性地触发,和Linux crontab格式兼容。它是功能最强大的触发器。参数详见
2.3 执行器(executor)

执行器是执行调度任务的模块。最常用的 executor 有两种:ProcessPoolExecutorThreadPoolExecutor

2.4 任务存储(job store)

存储预定的作业。默认job store只是将作业保存在内存中,但其他job store将它们存储在各种数据库中。作业的数据在保存到持久job store时被序列化,并在从它加载回来时被反序列化。job store(默认存储除外)不会将作业数据保存在内存中,而是充当中间人,用于在后端保存、加载、更新和搜索作业。job store绝不能在调度程序之间共享。

3. Flask框架实践

3.1 定时任务初始化

apscheduler在app创建时进行初始化, scheduler在初始化器类中进行创建,初始化器类采用单例设计, 在整个flask实例上下文中都是同一个对象,以满足通过接口进行动态更新任务的需求

# src.initializer.py
from apscheduler.schedulers.background import BackgroundSchedulerdef singleton(cls):_instance = {}def _singleton(*args, **kargs):if cls not in _instance:_instance[cls] = cls(*args, **kargs)return _instance[cls]return _singleton@singleton
class Initializer:def __init__(self):self.scheduler = BackgroundScheduler()

scheduler初始化之后可以通过add_job添加一些固定的定时任务, 再通过start方法就可以正式启动定时任务

# main.py
from flask_apscheduler import APScheduler
from src.initializer import Initializerdef create_app():app = Flask(__name__)app.config.from_object(Config)initializer = Initializer()update_job = {"id": "print_jobs","func": "src.utils.common.scheduler:update_jobs","args": (initializer.scheduler,),"trigger": "interval","seconds": 10,}initializer.scheduler.add_job(**update_job)initializer.scheduler.start()return app
3.2 通过接口进行任务动态增减

在初始化flask实例时进行了apscheduler单例化, 可以动态的通过flask接口进行定时任务的删除和新增.使用唯一的job_id进行任务的获取, 删除 和 新增.

from flask import current_app@app.route("/test_apscheduler")
def test_apscheduler():"""测试定时任务动态进行删除和新增任务"""ping_baidu = {"id": "ping_baidu","func": "src.utils.common.scheduler:ping","args": ("baidu.com",),"trigger": "interval","seconds": 10,}job = current_app.apscheduler.get_job(job_id="ping")if job:current_app.apscheduler.remove_job(job_id="ping")current_app.apscheduler.add_job(**ping_baidu)return http_json({"msg": "ok"})
3.3 通过定时任务自我进行任务动态管理

如上在进行flask初始化时有预设一个update_job的定时任务,传参为scheduler调度器, 每2分钟运行一次, 在内部实现任务从配置文件或数据库读取,然后进行任务的删除、更新、新增操作,以此达到定时任务的自我管理。

# 伪代码src.utils.common.scheduler.pydef update_job(scheduler):"""定时任务自我管理,动态更新job"""jobs = scheduler.get_jobs()new_jobs, expired_jobs = get_job_from_db(jobs)for job in expired_jobs:scheduler.remove_job(job_id=job.id)for job in new_jobs:scheduler.add_job(job)

4. 踩坑点

4.1 多进程部署,定时任务重复启动

解决思路: 在启动定时任务时, 设置文件锁, 当不能获取到文件锁时, 不再启动任务


def create_app():app =Flask(__name__)# 启动定时任务scheduler_init(app)return appdef scheduler_init(app):"""保证系统只启动一次定时任务"""if platform.system() != 'Windows':fcntl = __import__("fcntl")f = open('scheduler.lock', 'wb')try:fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)scheduler.init_app(app)scheduler.start()app.logger.debug('Scheduler Started,---------------')except:passdef unlock():fcntl.flock(f, fcntl.LOCK_UN)f.close()atexit.register(unlock)else:msvcrt = __import__('msvcrt')f = open('scheduler.lock', 'wb')try:msvcrt.locking(f.fileno(), msvcrt.LK_NBLCK, 1)scheduler.init_app(app)scheduler.start()app.logger.debug('Scheduler Started,----------------')except:passdef _unlock_file():try:f.seek(0)msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, 1)except:passatexit.register(_unlock_file)
4.2 多主机分布式部署,定时任务重复启动

apscheduler本身不支持分布式,因此分布式部署还是会出现重复启动问题.

可以多apscheduler进行分布式重写解决, 重写思路: 分布式场景下使用APScheduler 、apscheduler分布式调度

Apscheduler结合flask进行动态任务管理相关推荐

  1. Python Flask,动态路由,url参数,转换器

    demo.py(转换器,动态路由): # coding:utf-8from flask import Flaskapp = Flask(__name__)# 转换器 (动态路由) # 127.0.0. ...

  2. Flask 生成动态二维码登录

    看了很多篇生成动态二维码的帖子,但是,都是片段,前言后语都没有.主要研究的这篇 然后自身也不够理解flask基本语言结构,所以头大, 皇天不负有心人,后来看了一些教程,再加上同事小姐姐指导,终究是给跑 ...

  3. Spring boot2集成quartz动态任务管理+Web UI

    Dynamic Quartz ​ 最近在公司实习,发现公司有一套spring+Quartz的动态任务管理系统.可以使用Web界面进行任务动态的创建.删除.停止.运行和修改.刚好最近在学习spring ...

  4. 使用Redis+Flask维护动态代理池

    1.为什么使用代理池 许多⽹网站有专⻔门的反爬⾍虫措施,可能遇到封IP等问题. 互联⽹网上公开了了⼤大量量免费代理理,利利⽤用好资源. 通过定时的检测维护同样可以得到多个可⽤用代理理. 2.代理池的要 ...

  5. Python爬虫入门之使用Redis+Flask维护动态代理池

    代理池的要求 多站抓取, 异步检测 定时筛选, 持续更新 提供接口, 易于提取 代理池架构 代码 代码放到github上了,稍微修改了一点,可以正常运行了.有问题评论留言讨论. 分为两种ProxyPo ...

  6. Flask自定义转换器,实现路由匹配正则表达式参数

    Flask框架动态路由实现参数传递和Django框架有类似之处,但是相比于Django框架,Flask实现复杂的参数就需要自己自定义转换器来实现了,而不能向Django那样直接使用正则表达式 1 # ...

  7. flask基础(上篇)

    目录 一.flask入门与路由 二.flask路由 三.flask请求响应异常 flask入门与路由 1. flask介绍 Flask是一个基于Python实现的web开发的'微'框架 中文文档地址 ...

  8. flask静态html

    flask使用静态html 在flask并不是所有的html都需要做成动态html,并且做成动态html在使用静态资源时要改变它的路径.所以我们有些可以使用静态html. 静态html不需要后台渲染, ...

  9. python flask安装_python flask安装和命令详解

    Flask Web开发实战学习笔记 Flask简介 Flask是使用Python编写的Web微框架.Web框架可以让我们不用关 心底层的请求响应处理,更方便高效地编写Web程序.因为Flask核心简 ...

最新文章

  1. ccna实验配置个人总结
  2. HTML5+Bootstrap 学习笔记 1
  3. IDEA中Maven项目使用Junit4单元测试的写法
  4. 公司僵尸帐号引发了一系列的入侵事件-细说密码强度验证的重要性
  5. 95-290-240-源码-内存管理-StreamRecord-StreamRecord简介
  6. 18 线程池,线程安全队列,线程创建
  7. 深度学习入门笔记(六):误差反向传播算法
  8. php连接mysql执行sql语句_php+mysql 连接服务器、数据库以及执行SQL语句的类库
  9. 嵌入式操作系统_一个C++版的嵌入式操作系统
  10. 文字处理技术:搞明白了表格是如何参与文字方向的
  11. QT创建和使用动态链接库
  12. mysql常用语句之DQL:查询语句
  13. 分享39个大数据可视化工具(数据分析必备)
  14. 微信小程序运营之如何获取流量
  15. 微积分 导数 微分 偏导数 方向导数 梯度 向量 雅克比矩阵 概念
  16. 【pandas】set_index函数详解
  17. CCF-CSP 201912-2 回收站选址(python实现)
  18. Capstone CS5210|CS5210 HDMI to VGA转换器
  19. DHT11大气温湿度模块+直流电机实现根据温度控制风扇转动
  20. ad16以上的版本中怎么裁剪PCB板

热门文章

  1. ABP+AdminLTE+Bootstrap Table权限管理系统第五节--WBEAPI及SwaggerUI
  2. Mac 下面安装 Git 步骤
  3. 三维交通模拟html,三维高精度交通枢纽综合信息平台
  4. 似然函数取对数的原因
  5. html怎么安装整合包,上古卷轴5无心10.0整合包怎么安装_上古卷轴5无心10.0整合包安装教程_飞翔教程...
  6. jmeter文件上传
  7. html制作日历备忘录,CSS3制作日历备忘录
  8. Windows照片查看器无法显示此照片,因为计算机上的可用内存可能不足
  9. 读书笔记-《基于Oracle的SQL优化》-第二章-1
  10. java 解析m3u8的实例_m3u8文件完整实例及TS流抓取