(二十)Flask之上下文管理第一篇(粗糙缕一遍源码)

news2024/10/2 16:17:29

每篇前言:

  • 🏆🏆作者介绍:【孤寒者】—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 Flask

app = 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 头部。当你的应用程序决定如何响应请求时,它需要调用这个函数来开始发送响应)

在这里插入图片描述

继续进去:

在这里插入图片描述

上面选中那一句实现了三个功能:

  1. 将WSGI处理之后的请求数据environ又处理了一遍;
  2. 设置session为None;
  3. 实现路由匹配(根据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方法封装了这整个流程。

在这里插入图片描述

进去:

简单讲一下这个函数各语句功能:

  1. 触发首次请求前的函数:

    self.try_trigger_before_first_request_functions()
    

    这一行尝试触发任何注册为“在第一个请求之前执行”的函数。这些函数只会在应用收到其第一个请求时执行一次,通常用于一些应用的初始化工作。

  2. 发送请求开始信号:

    request_started.send(self)
    

    这一行发送一个request_started信号。Flask使用信号来允许开发者在某些事件(如请求开始或结束)发生时执行自定义代码。

  3. 请求预处理:

    rv = self.preprocess_request()
    

    这一行调用preprocess_request方法来执行任何注册的请求预处理函数,例如before_request钩子。这些钩子可以用于各种目的,如用户身份验证、设置数据库连接等。

  4. 请求分发:

    if rv is None:
        rv = self.dispatch_request()
    

    如果预处理函数没有返回任何值(即返回None),则该代码调用dispatch_request方法。dispatch_request方法的职责是根据当前请求的URL找到对应的路由和视图函数,并执行它。

  5. 请求后处理:

    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最为核心部分(上下文管理)的源码!
粗糙是粗糙,但味道没有错,仔细扣扣源码~
后续几篇文章会继续细化这部分!

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

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

相关文章

RT Thread Stdio生成STM32L431RCT6工程后如何修改外部时钟

一、简介 RT Thread Stdio生成STM32L431RCT6工程后默认为内部时钟,如何修改为外部时钟呢? 二、修改时钟步骤 本方案修改外部时钟为直接修改代码,不通过STM32CubeMX 进行配置(使用这个软件会编译出错) (…

C#用Convert.ToString(Int32, Int32)和Convert.Tolnt64(String, Int32)进行数值转换

目录 一、Convert.ToString(Int32, Int32) 方法 1.定义 2. 示例 二、Convert.ToInt64(String, Int32) 1.定义 2.实例 三、用Convert.ToString(Int32, Int32)和Convert.Tolnt64(String, Int32)进行数值转换 1.Main() 2.类库 3.生成效果 使用Convert.ToString(Int32…

GPT应用程序上线注意的问题

在将GPT应用程序上线之前,有一些重要的问题需要注意,以确保应用程序的成功运行、用户满意度和合规性。以下是一些建议,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 合规性和…

docker里Java服务执行ping命令模拟流式输出

文章目录 业务场景处理解决实现ping功能并实时返回输出实现长ping和中断请求docker容器找不到ping命令处理 业务场景 我们某市的客户,一直使用CS版本的信控平台,直接安装客户Windows server服务器上,主要对信号机设备进行在线管理、方案配时…

Windows下安装alipay-sdk-python时,pycrypto安装报错问题处理

1、安装alipay-sdk-python 时,保存内容如下。 Building wheels for collected packages: pycryptoBuilding wheel for pycrypto (setup.py) ... error error: subprocess-exited-with-error python setup.py bdist_wheel did not run successfully.│ exit c…

fastJson和jackson的日期数据处理

目录 1.jackson 2.fastjson 3.总结 1.jackson jackson是spring mvc默认的JSON解析方法,前端的数据序列化处理之后,后端经过反序列化处理可以直接使用实体对象进行接收。后端接口返回实体对象,经过序列化处理后前端可以接收并进行处理。 …

深度学习:探索人工智能的前沿

1. 引言 1.1 人工智能的演进 人工智能(Artificial Intelligence,简称AI)是一门研究如何使计算机能够执行通常需要人类智能的任务的领域。从早期的符号推理到现代的深度学习,人工智能经历了漫长的发展过程。 20世纪50年代&#xff…

Golang通过Gorm操作Mysql时遇到的datetime时区问题

情景描述 golang使用Gorm操作MySQL,MySQL中数据类型是datetime,Golang中用的是time.now。 但是会导致存储的时间与北京时间有8h误差, 显然是没有初始化时区导致。 问题修复 初始化设置时区 参考我自己之前写过的一篇总结——Mysql中多种日…

Qt应用开发(安卓篇)——Hello Qt On Android

一、前言 这一篇从实际出发,讲述如何创建、编译和部署Qt On Android项目。 二、ADB调试 ADB的全称为Android Debug Bridge,就是起到调试桥的作用,主要用于连接计算机与Android 设备,以便进行调试和数据传输。ADB 可以实现以下主要…

工作中使用Redis10种场景

前言 Redis作为一种优秀的基于key/value的缓存,有非常不错的性能和稳定性,无论是在工作中,还是面试中,都经常会出现。 今天这篇文章就跟大家一起聊聊,我在实际工作中使用Redis的10种场景,希望对你会有所帮…

快速傅里叶变化检测轻微划痕

像这种轻微划痕,普通算法鲁棒性差,通用性也不是很好,通过一些特殊处理,基本上可以满足客户需求. 图像处理,检测无非这个几个步骤. 预处理----分割----筛选—满足设定条件NG read_image (Image, ‘轻微划痕.bmp’) dev_close_window() get_image_size(Image, Width, Height) dev…

HTTPS:如何确保您的网站数据传输安全?

目录 博客前言 一.HTTPS 1.1 HTTPS简介 1.2 HTTP和HTTPS区别 1.3 TLS/SSL协议工作原理 1.3.1 TLS/SSL协议结构 1.3.2 SSL/TLS握手协议建立连接过程 1.2.3 SSL/TLS报文分析 博客前言 以下是一个关于HTTPS协议的博客前言示例: 欢迎来到我的博客,今…

vue 解决el-table 表体数据发生变化时,未重新渲染问题

效果图父组件中数量改变后总数重新计算 子组件完整代码 <template><el-tableshow-summaryref"multipleTable"v-bind"$props"selection-change"handleSelectionChange"row-click"handleRowClick":summary-method"getSum…

20230118-【UNITY 学习】增加攀登系统

替换脚本PlayerMovement_04.cs using System.Collections; using System.Collections.Generic; using UnityEngine;public class PlayerMovement_05 : MonoBehaviour {private float moveSpeed; // 玩家移动速度public float walkSpeed 7; // 行走速度public float sprintSpee…

基于麻雀优化算法SSA的CEEMDAN-BiLSTM-Attention的预测模型

往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 风速预测&#xff08;一&#xff09;数据集介绍和预处理-CSDN博客 风速预测&#xff08;二&#xff09;基于Pytorch的EMD-LSTM模型-CSDN博客 风速预测&#xff…

网络安全 | 苹果承认 GPU 安全漏洞存在,iPhone 12、M2 MacBook Air 等受影响

1 月 17 日消息&#xff0c;苹果公司确认了近期出现的有关 Apple GPU 存在安全漏洞的报告&#xff0c;并承认 iPhone 12 和 M2 MacBook Air 受影响。 该漏洞可能使攻击者窃取由芯片处理的数据&#xff0c;包括与 ChatGPT 的对话内容等隐私信息。 安全研究人员发现&#xff0c;…

论文阅读:Vary论文阅读笔记

目录 引言整体结构图数据集构造Vary-tiny部分Document Data数据构造Chart Data构造Negative natural image选取 Vary-base部分 引言 论文&#xff1a;Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models Paper | Github | Demo 许久不精读论文了&#x…

基于Harris角点的多视角图像全景拼接算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 Harris角点检测 4.2 图像配准 4.3 图像变换和拼接 4.4 全景图像优化 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 function [ImageB…

鸿蒙开发-ArkUI框架实战【日历应用 】

对于刚刚接触OpenHarmony应用开发的开发者&#xff0c;最快的入门方式就是开发一个简单的应用&#xff0c;下面记录了一个日历应用的开发过程&#xff0c;通过日历应用的开发&#xff0c;来熟悉基本图形的绘制&#xff0c;ArkUI的组件的使用&#xff0c;UI组件生命周期&#xf…

新版AndroidStudio dependencyResolutionManagement出错

在新版AndroidStudio中想像使用4.2版本或者4.3版本的AndroidStudio来构造项目&#xff1f;那下面这些坑我们就需要来避免了&#xff0c;否则会出各种各样的问题。 一.我们先来看看新旧两个版本的不同。 1.jdk版本的不同 新版默认是jdk17 旧版默认是jdk8 所以在新版AndroidSt…