flask_apscheduler源码分析

前言

    遵循flask框架的标准的库,都称为flask扩展,flask_apscheduler是对apscheduler的扩展,也称为flask的扩展,最近使用flask_apscheduler遇到了一个job死亡的bug。现象:job平时是正常启动的,突然某个时刻全部挂了。。

环境介绍

官方文档:https://viniciuschiele.github.io/flask-apscheduler/

    当前分析版本:1.12.4

    安装方式:pip install Flask-APScheduler

    源码位置:site-packages目录下

    

包结构介绍 

    flask_apscheduler是个包模块,包括__init__.py,共计6个模块

加载顺序

from flask_apscheduler import APScheduler

 一般情况下,我们会在flask程序中,写下如上一行,此时flask_apscheduler的__init__.py中没有缩进的代码开始执行

__init__.py分析

from apscheduler.schedulers.base import STATE_PAUSED, STATE_RUNNING, STATE_STOPPED
from .scheduler import APScheduler

主要做了两件事

1、从标准库apscheduler下的base模块中,导入几个全局变量

2、从当前包下的scheduler模块中导入APScheduler类

scheduler模块分析

我们主要分析的是flask_apscheduler包模块下的scheduler.py模块

 看了下这个scheduler.py模块共计400多行,我觉得还行

scheduler分析过程一:模块导入

import flask
import functools
import logging
import socket
import warnings
import werkzeugfrom apscheduler.events import EVENT_ALL
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.base import JobLookupError
from flask import make_response
from . import api
from .utils import fix_job_def, pop_trigger

总体的导入分3部分

1、标准库的导入

functools、logging、socket、warnings、apscheduler(重点依赖这个标准库)

2、第三方库

flask、werkzeug

3、自己写的模块

api、utils

整体说明:作者同时使用了标准库、比如logging用于日志打印的标准库,还有地方依赖库,当然是flask和werkzeug(flask依赖的底层网络库)、还有自己写的两个模块,api和utils。。

最最最重要的apscheduler的使用,尤其是导入BackgroundScheduler这个类

scheduler分析过程二:创建日志分析对象

LOGGER = logging.getLogger('flask_apscheduler')

 scheduler分析过程三:创建APScheduler类

class APScheduler(object):

         …………省略…………

 这个APScheduler创建的对象,是以后我们经常用的对象,作为整个模块的业务逻辑入口,后续单独开篇文章介绍这个类的封装。

初步总结

    scheduler就干了3件事、导入模块、创建日志分析对象、创建APScheduler类。

继续分析当前包模块

上面已经分析了__init__.py模块、还有scheduler.py模块,还记得scheduler.py下面这两句代码吗?

from . import api

from .utils import fix_job_def, pop_trigger

我们将继续分析api模块和utils模块,因为这俩模块先后加载到内存中了

api模块分析

scheduler.py模块加载的时候,导入了api.py模块,此时api.py模块没有缩进代码将会被执行

api模块分析过程一:模块导入

import loggingfrom apscheduler.jobstores.base import ConflictingIdError, JobLookupError
from collections import OrderedDict
from flask import current_app, request, Response
from .json import jsonify

 过程也是3部分

1、导入标准库(导入过的不会重复导入,所以这里写了也没事,内存中是同一个模块对象)

logging、apscheduler、collections模块

2、导入第三方库

flask

3、导入自己写的模块

json

api模块分析过程二:创建函数

1、连续创建了9个函数对象

2、且他们都与flask应用对象有所关联,我给找其中一个函数给大伙看看

def add_job():"""Adds a new job."""data = request.get_json(force=True)try:job = current_app.apscheduler.add_job(**data)return jsonify(job)except ConflictingIdError:logging.warning(f'Job {data.get("id")} already exists.')return jsonify(dict(error_message='Job %s already exists.' % data.get('id')), status=409)except Exception as e:logging.error(e, exc_info=True)return jsonify(dict(error_message=str(e)), status=500)

add_job,通过找个函数我们随时向调度器中添加一个job,可以说是一种动态添加job的方式!!

current_app 表示当前flask对象

current.apscheduler表示与之关联的Scheduler对象

return jsonify(job) 最终竟然也返回了一个响应,这是为啥呢?原来是flask_apscheduler给我们留的后门!!

在Scheduler类中,有个方法,是在框架中唯一使用这些api模块中的函数的地方

开关在这里,原来我们可以通过SCHEDULER_API_ENABLED,这样的flask配置修改是否开启快捷开关,这里不看源码,是肯定不知道有这个后门的,看来我也要开启了

 

初步总结

    api模块中的函数,可以在当前flask应用注册路由,那样我们通过http请求,就能操作job了,非常的方便debug呀,爽..

utils模块分析

 

    这个模块,看名字就知道是工具模块了,我们看看这个模块加载的时候干了什么

utils.py模块分析过程一:模块导入

import dateutil.parser
import sixfrom apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.date import DateTrigger
from apscheduler.triggers.interval import IntervalTrigger
from collections import OrderedDict

 1、标准库

collections

apscheduler

2、第三方库

dateutil

six

utils.py模块分析过程二:创建几个函数

作者真是代码写的干净利索啊,牛逼,这几个函数要工具相关,比如job转为字典,看来是来兜底用的模块,厉害,抽空看看几个函数具体是干啥的

json模块分析

 

json模块分析过程一:模块导入

from __future__ import absolute_importimport datetime
import flaskfrom apscheduler.job import Job
from .utils import job_to_dictimport json  # noqa

1、标准库

__future__

datetime

apscheduler

json

2、 三方库

flask

看来这个模块主要是操作json格式的

json模块分析过程二:创建全局变量

loads = json.loads

 拿来注意体现的好啊,创建一个loads全局变量,指向的是json模块下的loads函数,这样以后用这个函数就轻松了……

json模块分析过程三:创建函数

创建的dumps函数和jsonify函数 

json模块分析过程四:创建类

class JSONEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, datetime.datetime):return obj.isoformat()if isinstance(obj, Job):return job_to_dict(obj)return super(JSONEncoder, self).default(obj)

创建了一个用于编解码json的类

剩下的auth.py模块分析

 

剩下一个auth.py模块,我没找到该模块加载的位置,不知道在哪用的。。。。

总结

1、flask_apschduler依赖标准库apschduler、只不过做了一个与flask对象上下文的结合

2、比如可以通过flask的路径,直接创建job、删除job、甚至查看job状态(但是感觉不安全啊)

3、可以继续深入到模块中的Scheduler类中继续分析,可以看到job是有挂掉的可能的。

4、看源码收获每次都是满满的,爽。。。 

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

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

相关文章

MODNet 剪枝再思考: 优化计算量的实验历程分享

目录 1 写在前面 2 模型分析 3 遇到问题 4 探索实验一 4.1 第一部分 4.2 第二部分 Error 1 Error 2 4.3 实验结果 ①参数量与计算量 ②模型大小 ③推理时延 5 探索实验二 5.1 LR Branch 5.2 HR Branch 5.2.1 初步分析 5.2.2 第一部分 enc2x 5.2.3 第二部分 en…

量化交易科普

量化 语言和逻辑层面,用量词指定一个谓词的有效性的广度的构造 一些、很多、所有 量化交易 针对可交易的投资商品,理性地运用逻辑分析和归纳统计判断市场趋势 量化策略 常用的股票量化指标 相关平台 财经网站:新浪、雅虎、东方财富等 证券公…

php正则电话号

400电话的正则/^400[0-9]{7}/ 800电话正则/^800[0-9]{7}/ 手机号码正则/^1(3|4|7|5|8)([0-9]{9})/ 座机号码正则^0[0-9]{2,3}-[0-9]{8} 要匹配其中之一就在中间以|隔开 (400正则)|(800正则)|(手机号)|(座机号)| $phone preg_replace("/\s| /","",$p…

百度网盘网页无法调起客户端 目前未解决 2024年1月出现BUG

最近一周突然发现百度网盘网页无法调起客户端,多方式排查还是没找出问题所在,怀疑是客户端更新了什么东西导致bug。先记录下各种排查法和复现情况。 具体问题是: *任意网盘链接,都无法唤醒客户端。 *客户端在退出状态网页点击下…

数据结构(C语言版)代码实现(三)——单链表部分代码实现

目录 格式 头文件 宏定义 线性表的单链表存储结构 按位查找 插入元素 删除元素 头插法建立单链表 合并非递减单链表 其他基本操作 完整版 测试代码(主函数) 测试结果 格式 参考 2.3节 线性表的链式表示和实现 头文件 宏定义 #pragma onc…

GBASE南大通用数据库通过 GBase ADO.NET 接口读取数据

通过 GBase ADO.NET 接口读取 GBase Server 数据需要下面的步骤: 1) 使用 GBaseConnection 创建数据库连接对象 2) 使用 GBaseCommand 创建命令对象 3) 使用连接对象打开连接 4) 设置命令对象的 CommandText 属性,指明查询语句,并关联连接对…

html+css+javascript实现贪吃蛇游戏

文章目录 一、贪吃蛇游戏二、JavaScript三、HTML四、CSS五、热门文章 一、贪吃蛇游戏 这是一个简单的用HTML、CSS和JavaScript实现的贪吃蛇游戏示例。 HTML部分&#xff1a; <!DOCTYPE html> <html> <head><title>贪吃蛇游戏</title><styl…

【C++】命名空间详解

目录 前言 命名空间的定义 命名空间的使用 前言 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存 在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c; 以…

【LeetCode力扣】面试题 17.14. 最小K个数(top-k问题)

目录 1、题目介绍 2、解题思路 2.1、优先队列解法 2.2、top-k问题解法 1、题目介绍 原题链接&#xff1a;面试题 17.14. 最小K个数 - 力扣&#xff08;LeetCode&#xff09; 题目要求非常简短&#xff0c;也非常简单&#xff0c;就是求一组数中的k个最小数。 2、解题思路 …

数据结构:完全二叉树(递归实现)

如果完全二叉树的深度为h&#xff0c;那么除了第h层外&#xff0c;其他层的节点个数都是满的&#xff0c;第h层的节点都靠左排列。 完全二叉树的编号方法是从上到下&#xff0c;从左到右&#xff0c;根节点为1号节点&#xff0c;设完全二叉树的节点数为sum&#xff0c;某节点编…

【重点问题】攻击面发现及管理

Q1&#xff1a;在使用长亭云图极速版时&#xff0c;是否需要增设白名单扫描节点&#xff1f; 长亭云图极速版高级网络安全产品基于一种理念&#xff0c;即攻击面发现是一个不断变换且需要持续对抗的过程。在理想的情况下&#xff0c;用户应当在所有预置防护设施发挥作用的环境…

C++面试:stl的栈和队列介绍

目录 栈 栈&#xff08;stack&#xff09;的声明&#xff1a; push()&#xff1a; 将元素推入栈顶 pop()&#xff1a; 弹出栈顶元素 top()&#xff1a; 访问栈顶元素&#xff0c;但不弹出 empty()&#xff1a; 检查栈是否为空 size()&#xff1a; 返回栈中元素的数量 …

【MQ01】什么是消息队列?用哪个消息队列?

什么是消息队列&#xff1f;用哪个消息队列&#xff1f; 来了来了&#xff0c;消息队列系列总算来咯。对于搜索引擎相关的知识大家消化的怎么样呀&#xff1f;其实对于搜索引擎来说&#xff0c;我们学习的内容还是挺全面的&#xff0c;也算是比较深入了。而对于消息队列来说&am…

6.第一个Python爬虫程序

使用 Python 内置的 urllib 库获取网页的 html 信息。注意&#xff0c;urllib 库属于 Python 的标准库模块&#xff0c;无须单独安装&#xff0c;它是 Python 爬虫的常用模块 获取网页html信息 1) 获取响应对象 向百度&#xff08;百度一下&#xff0c;你就知道&#xff09;…

uniapp使用uni-forms表单校验无效

查看是否写了name属性&#xff0c;且name属性的属性值得和下面v-model绑定的一致&#xff0c;否则校验不生效 官网

一种解决常用存储设备无法被电脑识别的方法

一、通用串行总线控制器描述 通用串行总线&#xff08;Universal Serial Bus&#xff0c;简称USB&#xff09;&#xff0c;是连接电脑与设备的一种序列总线标准&#xff0c;也是一种输入输出&#xff08;I/O&#xff09;连接端口的技术规范&#xff0c;广泛应用于个人电脑和移动…

关于大模型学习中遇到的4

来源&#xff1a;网络 相关学习可查看文章&#xff1a;Transformer and Pretrain Language Models3-4​​​​​​​ 什么是MLP? MLP是多层感知器&#xff08;Multilayer Perceptron&#xff09;的缩写&#xff0c; 多层感知机&#xff08;MLP&#xff09;是一种人工神经网…

【C++】初步认识基于C的优化

C祖师爷在使用C语言时感觉到了不方便的一些点&#xff0c;于是一步一步改进优化&#xff0c;最后形成了C 本文将盘点一下基于C的语法优化 目录 命名空间&#xff1a;命名空间定义&#xff1a;命名空间使用&#xff1a; C输入&输出&#xff1a;cout&#xff1a;endl&#…

vue项目开发的完整流程

一.构建vue.js项目 1. 安装node https://nodejs.org/en/ 下载完成后&#xff0c;下一步–>下一步–>安装完成 验证node是否安装成功: 打开命令行(windows)或终端(mac),在命令行(终端)中输入&#xff1a; node -v 如果提示出版本信息则说明node安装成功 npm -v 如果提示出…

使用django-admin来做erp,是否需要使用缓存数据库

需求: 因为添加了手机字段作为加密方式存储&#xff0c; 每次管理员查看所有订单时&#xff0c;将会进行手机字段的解密&#xff0c;那么在这个时候就会消耗多几秒. 那么计划提供一个缓存数据库给django结论&#xff1a;仅仅使用django admin&#xff0c;不需要使用缓存 1&…