阅读flask源码2:Local,LocalStack

2024-03-16 22:08

本文主要是介绍阅读flask源码2:Local,LocalStack,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们还是以flask0.1的代码来阅读,先提出几个常见的问题:

1上下文是怎么被压入栈的?

2为什么在不同的程序中通过相同的变量request可以拿到对应的请求

我们先看第一个问题:上下文是怎么被压入栈的?

服务器传过来的请求参数,被封装成了一个_RequestContext对象,这个对象里有这个请求相关联的一组互相“绑架”的参数,它们组成一个上下文环境。比如request,被实例化的app。如下:

class _RequestContext(object):def __init__(self, app, environ):self.app = appself.url_adapter = app.url_map.bind_to_environ(environ)self.request = app.request_class(environ)self.session = app.open_session(self.request)self.g = _RequestGlobals()self.flashes = Nonedef __enter__(self):_request_ctx_stack.push(self)def __exit__(self, exc_type, exc_value, tb):# do not pop the request stack if we are in debug mode and an# exception happened.  This will allow the debugger to still# access the request object in the interactive shell.if tb is None or not self.app.debug:_request_ctx_stack.pop()

这个对象实现了__enter__,所以通过with context语句。对象被压入到一个栈中。

 def push(self, obj):"""Pushes a new item to the stack"""rv = getattr(self._local, "stack", None) # 如果没有stack,那么就返回none,然后给_local创建一个stack属性。if rv is None:self._local.stack = rv = [] # 新建一个列表,把这个列表给自己的属性_local,它是一个对象。rv.append(obj) # 给自己的属性_local的属性,加上一个上下文环境对象,这个对象在请求进来时已经通过with实例化了一个。return rv

字典的键是线程Id,值就是被压入的,封装了特定请求的上下文对象。那么问题来了,正常情况下,context被压入栈中,栈里应该是context对象啊。是怎么实现里面有字典的呢?

压入栈中,这个压入,可不是压入一个普通的列表,这个列表,将做为Local对象的一个属性stack

这个LocalStack初始化的时候,封装了一个Local对象。为什么要这样做呢?这就回答了上面的问题,Local可以实现线程隔离,拿到当前线程的上下文。

这里Local实现了一个__setattr__方法,这样可以加上线程了,现在上下文按放在一个Local对象的字典中,

上面是存储好了上下文环境 ,下面是讲解,怎么通过全局变量拿到request的呢?

我们进入视图函数了,我们输入:request.url。

@app.route('/')
def index():req = request.urlreturn req

这个时候,request是一个代理对象,

request = LocalProxy(lambda: _request_ctx_stack.top.request)

_request_ctx_stack.top.request)会从栈中取出最上面的对象,并且拿到栈最上面的上下文对象。

它本身没有url属性,所以会触发LocalProxy的__getattr__属性。这个时候,拿到request对象的url属性。

这篇关于阅读flask源码2:Local,LocalStack的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/816864

相关文章

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显