(二十)Flask之上下文管理第一篇(粗糙缕一遍源码)
每篇前言:
🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者
- 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入门到实战》
- 🔥🔥热门专栏推荐:《Python全栈系列教程》、《Django框架从入门到实战》、《爬虫从入门到精通系列教程》、《前端系列教程》、《tornado一条龙+一个完整版项目》。
- 📝📝本专栏面向广大程序猿,为的是大家都做到Flask从入门到精通,穿插有很多实战优化点。
- 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!
![]()
引子:
当一个客户端,比如浏览器,向 Flask 服务发起 HTTP 请求,它首先会被 Web 服务器(如 gunicorn 或 uWSGI)接收。这个 Web 服务器的任务不仅仅是接收请求,它还作为 Flask 应用程序与外部环境之间的桥梁。
为了使 Web 服务器和 Python Web 应用程序能够“对话”,我们需要一个规范或者说是一个协议。这就是 WSGI,即 Web Server Gateway Interface。Flask 利用 Werkzeug 这一 WSGI 工具库来满足这个规范的需求。
现在,当一个 HTTP 请求达到 Web 服务器,Werkzeug 会介入并起到关键作用。它的职责是从原始 HTTP 请求中提取出有意义的数据,并将其转化为 Flask 可以轻松操作的格式。这意味着,原始的请求数据如:
GET /index.html HTTP/1.1
Host: www.example.com
会被 Werkzeug 解析,并且转化为 Flask 可以直接使用的请求对象,比如 flask.request。这样,开发者可以轻松地访问请求的各个部分,例如 headers、query parameters、body 等,无需深入了解底层的 HTTP 协议。
简而言之,通过 WSGI 和 Werkzeug 的配合,当 HTTP 请求达到 Flask 应用时,我们可以直观、高效地处理它,使开发变得更为简洁。
看源码捋一下一个完整请求在Flask里整个生命周期都干了啥?
前面讲过请求一旦到来,就会执行app.__call__方法:
from flask import Flaskapp = Flask(__name__)@app.route('/')
def hello_world():return 'hello world'if __name__ == '__main__':app.__call__app.run()
进入__call__方法:
【需要注意的是:参数environ 已经是一个经过 WSGI 服务器处理后的字典,它包含了所有与 HTTP 请求相关的信息。即当一个 HTTP 请求到达 WSGI 服务器时,服务器会解析这个请求,并将相关的信息转化为 environ 字典中的一系列键值对!】
(拓展:start_response 是 WSGI 规范中定义的一个回调函数,它的主要作用是设置响应的状态和 HTTP 头部。当你的应用程序决定如何响应请求时,它需要调用这个函数来开始发送响应)

继续进去:

上面选中那一句实现了三个功能:
- 将WSGI处理之后的请求数据environ又处理了一遍;
- 设置session为None;
- 实现路由匹配(根据url找到对应视图函数)。
下面扣源码来证实~
进去request_context:

继续进去:
- 下图第一个箭头所指位置就是功能一:将WSGI处理之后的请求数据environ又处理了一遍。主要任务就是将 WSGI 提供的
environ字典转换为 Flask 可以更容易处理的请求对象(可以自己继续进源码去探究) - 下图第二个箭头所指位置就是功能二:设置session为None。

而上图最后一个箭头所指位置就是功能三:实现路由匹配(后续深入讲解)~
回到wsgi_app函数,继续下一句:

进去:

其他部分先不管,直接看上图箭头所指位置,是不是很眼熟?
- 这部分就是Flask使用了自己实现的threading.local()对象!
进去_request_ctx_stack对象:

进去LocalStack()对象:

回退两层:
下图箭头所指就是给ctx里的session赋值:
- 下图倒数第三行调用了应用对象(通常是一个Flask应用实例)的
open_session方法,并传入当前的请求对象self.request。这个方法的目标是从请求中提取会话数据(如果存在的话)并返回一个会话对象。 - 如果
open_session没有返回一个有效的会话对象(例如,当前请求可能是一个全新的请求,没有任何之前的会话数据),那么self.session将为None。在这种情况下,代码会调用make_null_session方法来创建一个新的、空的会话对象。这确保了self.session始终有一个有效的会话对象,无论是从请求中提取的还是新创建的空会话。

回去继续往下扒:
下图箭头所指就是Flask用于处理一个请求并返回相应响应的核心逻辑:
- 当一个HTTP请求到达Flask应用时,它需要经过一系列的处理步骤,如:预处理(前置处理),路由匹配,视图函数处理,以及后处理(后置处理)等,然后最终得到一个HTTP响应(response)。
full_dispatch_request方法封装了这整个流程。

进去:
简单讲一下这个函数各语句功能:
触发首次请求前的函数:
self.try_trigger_before_first_request_functions()这一行尝试触发任何注册为“在第一个请求之前执行”的函数。这些函数只会在应用收到其第一个请求时执行一次,通常用于一些应用的初始化工作。
发送请求开始信号:
request_started.send(self)这一行发送一个
request_started信号。Flask使用信号来允许开发者在某些事件(如请求开始或结束)发生时执行自定义代码。请求预处理:
rv = self.preprocess_request()这一行调用
preprocess_request方法来执行任何注册的请求预处理函数,例如before_request钩子。这些钩子可以用于各种目的,如用户身份验证、设置数据库连接等。请求分发:
if rv is None:rv = self.dispatch_request()如果预处理函数没有返回任何值(即返回
None),则该代码调用dispatch_request方法。dispatch_request方法的职责是根据当前请求的URL找到对应的路由和视图函数,并执行它。请求后处理:
return self.finalize_request(rv)最后,无论请求处理过程中是否发生异常,
finalize_request方法都会被调用。它负责执行任何注册的请求后处理函数(例如after_request钩子)并返回最终的HTTP响应。综上所述,
full_dispatch_request方法封装了Flask处理HTTP请求的整个流程,包括前后处理、路由分发、异常处理和最终响应的创建。

先进去preprocess_request()函数:
【可以看到确实在执行所有注册的请求预处理函数,例如before_request钩子】

回去一层,进去finalize_request()函数:

继续进去:

继续进去:
重要部分:
self.session_interface是Flask应用中用于处理会话的接口。is_null_session方法检查给定的会话(在这里是ctx.session)是否是一个空会话。如果不是一个空会话(也就是说,会话中包含了一些数据),那么条件判断为真。- 当条件判断为真时,
save_session方法将当前的会话数据(ctx.session)保存到响应中(response)。这通常涉及将会话数据加密并设置为一个Cookie,然后将该Cookie附加到HTTP响应中。这样,当浏览器接收到这个响应时,它会保存这个Cookie,并在后续的请求中将其发送回服务器。这使得服务器能够识别并“记住”用户之间的连续请求。

回到最开始:

继续进去:

继续进去:

看看_request_ctx_stack对象是啥呢?

进去:
【threading.local()对象???:是的!】

文末扯几句:
本文较为粗糙地捋了一遍Flask最为核心部分(上下文管理)的源码!
粗糙是粗糙,但味道没有错,仔细扣扣源码~
后续几篇文章会继续细化这部分!
相关文章:
(二十)Flask之上下文管理第一篇(粗糙缕一遍源码)
每篇前言: 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入…...
Tensorflow2.0笔记 - 基础数学运算
本笔记主要记录基于元素操作的,-,*,/,//,%,**,log,exp等运算,矩阵乘法运算,多维tensor乘法相关运算 import tensorflow as tf import numpy as nptf.__version__#element-wise运算,对应元素的,-,*,/,**,//,% tensor1 tf.fill([3,3], 4) ten…...
年底聚餐无压力,HUAWEI WATCH GT 4 助力体形管理和健康守护
过了腊八就是年,逢年过节聚餐频繁。在品味美食、享受亲情温馨的同时,你是否也在担心自己的健康与体形呢?华为WATCH GT 4搭载心率监测、血氧检测和减脂塑形等功能,让你尽情享受美食的同时保持健康。 华为WATCH GT 4的心率监测功能…...
Tomcat Notes: URL Mapping
This is a personal study notes of Apache Tomcat. Below are main reference material. - YouTube Apache Tomcat Full Tutorial,owed by Alpha Brains Courses. https://www.youtube.com/watch?vrElJIPRw5iM&t801s 1、URL Mapping To Resources1.1、What w…...
【JVM】JVM概述
JVM概述 基本介绍 JVM:全称 Java Virtual Machine,即 Java 虚拟机,一种规范,本身是一个虚拟计算机,直接和操作系统进行交互,与硬件不直接交互,而操作系统可以帮我们完成和硬件进行交互的工作特…...
【2023开发组二等奖】湖南省国土空间规划双评价系统
作品介绍 1 需求分析 1.1 背景与意义 在我国辽阔的国土空间中,各地区的地形地势、自然条件和资源环境禀赋存在显著差异。然而,随着人口增长和城市化进程加快,高强度的不合理开发和产业布局广泛分布,使得部分地区的经济社会发展规模超过了资源环境的承载能力。因此,执行主…...
Flutter为什么不需要子线程——Dart IO源码剖析(上)
Dart IO 源码剖析 许多Flutter新手,特别是安卓、iOS原生开发转做Flutter的小伙伴,一直对Flutter 单线程模型开发APP倍感不解,他们总是喜欢本能的把网络请求、文件读写放到一个单独线程去做,因为“耗时操作会阻塞UI线程嘛”。于是…...
docker使用Dockerfile制做容器(以hyperf为列,开机启动)
1、Dockerfile文件 FROM hyperf/hyperf:8.1-alpine-v3.18-swoole WORKDIR /data MAINTAINER dade <dadeqq.com> ADD start.sh start.sh RUN chmod x ./start.sh CMD /data/start.sh1-1、执行命令生成hyperf:latest容器(文件名是Dockerfile可以省略࿰…...
PDF转PowerPoint - Java实现方法
通过编程实现PDF转PPT的功能,可以自动化转换过程,减少手动操作的工作量,并根据需要进行批量转换。将PDF文件转换为PPT文档后,可以利用PPT的丰富功能和动画效果,达到更好的演示效果。 在Java中,我们可以使用…...
【Spring之手写一个依赖注入容器】
Spring之手写一个依赖注入容器 1. 创建两个自定义注解1.1 Component注解1.2 DI注解 2. ApplicationContext接口与实现类2.1 ApplicationContext 接口2.2 实现类:DefaultListableApplicationContext 3. 定义DAO层和Service层及其实现4. 定义异常信息类4.1 InjectBean…...
kafka之java客户端实战
1. kafka的客户端 Kafka提供了两套客户端API,HighLevel API和LowLevel API。 HighLevel API封装了kafka的运行细节,使用起来比较简单,是企业开发过程中最常用的客户端API。 而LowLevel API则需要客户端自己管理Kafka的运行细节,Pa…...
图解渠道网关:不只是对接渠道的接口(一)
这是《百图解码支付系统设计与实现》专栏系列文章中的第(20)篇。点击上方关注,深入了解支付系统的方方面面。 主要讲清楚什么是渠道,有哪些类型的渠道,什么是渠道网关,渠道网关在支付系统中定位、核心功能…...
【js版数据结构学习之队列】
队列 一、简要认识队列二、队列的封装三、队列的应用1.栈和队列的转换2.全排列3.任务调度4.缓存管理 一、简要认识队列 结构:一种特殊的线性表 入队:在队尾插入一个元素 出队:在队头删除一个元素 特点:先入先出 空队列࿱…...
iOS Xcode 升级Xcode15报错: SDK does not contain ‘libarclite‘
iOS Xcode 升级Xcode15报错: SDK does not contain libarclite 一、仔细查看报错代码: SDK does not contain libarclite at the path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/ lib/arc/libarclite_iphonesimulator.a; try in…...
python高级练习题库实验2(B)部分
文章目录 题目1代码实验结果题目2代码实验结果题目总结题目1 注册课程小游戏程序 研究下面的例子,并编写一个与这些例子完全相同的程序。使用for loop和break来解决问题。提示用户输入课程数量,是否选择,并且课程代码,最后还需显示已经完成的课程注册数量或者未完成的注册…...
vue项目编译非常慢,经常卡在某个百分点
1、注册插件 2、在项目根目录下的 babel.config.js 文件中加入下方配置 3、将import导入方式改为require导入方式,返回promise 4、如果动态加载组件import引入组件找不到组件(Error: Cannot find module) 使用 webpack 的 require.ensure() …...
开源知识库zyplayer-doc部署指南
1.前置条件 docker已经安装 mysql已经安装且数据库zyplayer-doc存在 服务器ip:192.168.168.99/ 数据库账户:root,密码:123456 2.拉取镜像 docker pull zyplayer/zyplayer-doc:latest 3.启动 docker run -d \--restart unless-stopped \--name zyplayer-doc \-p 8083:8083 …...
第90讲:MySQL数据库主从复制集群原理概念以及搭建流程
文章目录 1.MySQL主从复制集群的核心概念1.1.什么是主从复制集群1.2.主从复制集群中的专业术语1.3.主从复制集群工作原理1.4.主从复制中的小细节1.5.搭建主从复制集群的前提条件1.6.MySQL主从复制集群的架构信息 2.搭建MySQL多实例环境2.1.在mysql-1中搭建身为主库的MySQL实例2…...
PHP反序列化漏洞-魔术方法绕过
一、__wakeup()魔法函数绕过: 在PHP中,__wakeup()是一个魔术方法,用于在反序列化对象时自动调用。当反序列化字符串中的对象属性个数大于实际属性个数时,可以利用这个漏洞进行绕过。 触发条件: PHP版本为5.6.25或早期版本,或者PHP7版本小于7.0.10。反序列化字符串中的对…...
抖店和商品橱窗的区别?这两个千万别再搞混了!
我是电商珠珠 很多人都会将抖店和商品橱窗搞混,想开抖店的人开了商品橱窗,想开橱窗的人开通了抖店。 我做抖店三年了,这种情况屡见不鲜。 那么抖店和商品橱窗究竟有什么区别呢? 1、属性不同 商品橱窗是抖音所展现商品的一个功…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...
