面试官问及web框架中的上下文机制时,通常指的是在处理请求过程中的上下文环境管理。这一机制通过线程局部变量或者其他方式,将请求的相关信息(如请求头、请求参数等)保存在上下文中,使得在整个请求处理过程中能方便地访问这些信息。上下文机制的作用在于简化开发人员编写代码的复杂度,提高代码的可维护性和可读性。另外,它也为实现请求级别的状态管理提供了便利,同时能够支持并发请求的隔离,确保请求处理的线程安全性。总之,上下文机制为web框架提供了一种有效的方式来管理请求的相关信息,为开发人员提供了便捷的编程接口。
本文基于python的Flask框架,分享其上下文机制的实现和原理。在Flask中,上下文机制是最核心的概念之一。不仅仅是因为通过上下文机制实现了客户端和服务器交互简单化的目的,更为了flask的生态发展,可插拔式的组件开发提供了很好的支持。
You Deserve A Better Life
01
什么是Flask中的上下文?
从生活中理解Flask的上下文
假设说你要去取快递(发送请求),你来到了快递站点,然后你需要告诉工作人员你的快递单号,你的电话号码等个人信息,工作人员才会在系统中(系统中的信息可以理解为已经创建好的上下文代理,只有当你的信息需要被需要时,才会动态生成你的信息)查找,会根据你的提货码将快递取出给你(根据你提供的上下文信息给出响应),并在系统中修改为此快递已被取走(删除此次的上下文信息)
专业化的解释
上下文其实就是你向服务器发送请求时所需要的资料(包括请求参数,配置,验证等等),需要的时候取资料,用完则释放
02
flask中的上下文变量有哪些
flask中的上下文变量一共有4个,分为两类,分别是请求上下文和应用上下文
请求上下文:request和session
request:客户端的请求参数session:作为用户唯一标志,一般用来做用户登录状态的记录等程序上下文:current_app和g
current_app:指向当前应用实例g:一次请求中的全局变量,负责加载当前请求的一些操作,比如说连接数据库,响应结束,连接关闭
03
源码解读
先来看看上下文变量在哪里,怎么写的
我们知道Proxy是代理的意思,那么也就是说,这几个上下文变量其实都是通过代理类实现的,我们研究下这个代理类
代理类
实例方法中,object.__setattr__(self, "_LocalProxy__local", local)这个写法可能有人不太理解,其实等价于self.__local = local
其实就是类的私有变量(双下划线属性)进行外部调用的写法
这个local是必须要传进来的变量,是一个偏函数,那么啥叫偏函数?
偏函数
通过上述我们知道偏函数其实就是调用原有函数,只不过可以添加需要传递的参数,这样在后面调用偏函数时就可以少传递几个变量,那么我们看下上下文变量的偏函数都干了什么(用request举例)
总结来说:上下文变量request就是通过代理类拿到了请求上下文的RequestContext中的request属性,这个request属性拥有客户端请求的所有参数。
既然属性已经拿到了,就可以使用request.method,request.args等方式进行调用客户端参数,这个调用的原理又是什么呢?
既然是request对象进行调用,而request又是LocalProxy的代理类的对象,我们知道,"对象点方法"的使用,是去类中寻找__getattr__方法,那么我们看下这个方法
LocalProxy.__getattr__方法
这个方法基于反射原理,实现了动态取request对象中存在的方法,看下源码
通过上述的过程,request对象成功的找到了method方法。同理,但凡是需要使用的客户端的请求参数,就是在这里根据不同的name进行反射提取
其他几个上下文变量实现的方法大同小异,都是通过代理类(除了current_app),偏函数,反射实现,这里就不作一一的解释了。
04
应用上下文作用和意义
官方文档
应用上下问存在的主要原因是,在过去,请求上下文被附加了一堆函数,但是又没有什么好的解决方案。因为 Flask 设计的支柱之一是你可以在一个 Python 进程中拥有多个应用。
那么代码如何找到“正确的”应用?在过去,我们推荐显式地到处传递应用,但是这会让我们在使用不是以这种理念设计的库时遇到问题。
解决上述问题的常用方法是使用后面将会提到的current_app代理对象,它被绑定到当前请求的应用的引用。既然无论如何在没有请求时创建一个这样的请求上下文是一个没有必要的昂贵操作,应用上下文就被引入了。
我的理解
这样设计的优势在于上下文的推送和删除是动态进行的,如果需要使用,则动态的加载,不需要使用,则放在内存中不用管。
收集不易,本文《深入探讨:web框架中的上下文机制实现与作用》知识如果对你有帮助,请点赞收藏并留下你的评论。