werkzeug 中localstack的理解 您所在的位置:网站首页 FLask之Local、LocalStack和LocalProxy介绍 werkzeug 中localstack的理解

werkzeug 中localstack的理解

2024-07-18 04:43| 来源: 网络整理| 查看: 265

首先最近在学习flask的时候,对flask上下文的原理不是太清楚,关于localstack的实现逻辑不是很清楚,于是各种百度了解了下,这里写过博客备忘下,首先在理解localstack之前,我们要先了解下python自带的thread.local。

thread.local(代码都是伪代码实现,主要是说明下逻辑)

假如我们现在线程里面实现一个循环,肯定是在线程里面定义一个局部变量a,然后对a进行循环操作:

def xh(): for i in range(a): print i t1 = Thread(target=xh,name="xunhuan") t1.start() t1.join()

但是如果我们想公用一个全局变量a的话,就会有些麻烦了,只能把a当作参数传递到函数中去,而且如果在方法里面还要对a的值修改的话,还得加锁,要不然多个线程会导致数据不一致,操作起来很麻烦,于是thread.local诞生了,thread.local对象有一个map属性,key是线程id,value是变量的副本,每个线程操作变量的时候都去操作自己线程的变量副本,从而实现了线程间的隔离,互不干扰

local = Thread.local() local.g = 10 def xh(): for i in range(local.g): print i t1 = Thread(target=xh,name="xunhuan") t2 = Thread(target=xh,name="xunhuan2") t1.start() t2.start() t1.join() t2.join()

到这里大家对python自带的threadlocal有了一定的理解,threadlocal虽然很好的解决了我们的问题,但是对于一些并发应用还是有些不足,比如我们web应用,服务器对每个请求都会开启一个线程去响应用户的请求,而去响应这个请求的就是我们web应用,对于这种每个请求一个线程的情况,我们上下文完全可以通过threadlocal来实现,但是我们web服务的一个线程并不是只处理一个请求的,可能个请求的后续请求都是这个线程在处理,这个时候我们的上下文就会问题了,而且现在还有了用协程来处理并发的情况,一个线程是可以有多个协程的,所以这个时候threadlocal 就无法满足了,于是werkzeug 贴心的给了一个新的选择

werkzeug.local/localstack

local与python自带的thread.local的区别在于,local支持了协程,字典里的key存的是线程的数值信息或者协程的数值信息,而localstack则是对local的二次封装,并且数据结构不再是字典而是栈; 当有新的请求的时候,会生成新的请求上下文,并且压入(push)栈,这样栈顶永远都是存储的当前请求的上下文,并且localstack提供了一个top方法可以让我们取到这个栈顶对象,但我们的请求结束的时候,会调拥pop方法,将请求上下文移除栈,这样就保证了文并发的情况下,实现了请求上下文的效果

这里演示下,扩展模块flask_login中的current_user

请求开始: user = localstack() user .push(current_user) 获取current_user: current_user = user .top() 请求结束: user .pop()

这里其实还有个问题,current_user这个时候变量已经生成了,但是如果这个时候我当前的请求已经结束了,user已经被移除栈了,当前的user已经变动了,而我们current_user指向的还是之前的user,如果后续请求如果还是当前的线程在处理的话,current_user对象的信息就不匹配了,所以werkzeug给我们提供了一个代理,localproxy

loaclproxy

通过loaclproxy对象代理,我们就可以保证current_user对象是动态的,时刻保持是最新的user信息

a = user() a.name = 张三 b= user() b.name= 李四 user.push(a) user.push(b) def get_current_user(): return user.top() localproxy= localproxy(get_current_user) print(loclaproxy.name) user.pop() print(localproxy.name) ------- 李四 张三

代理的实现原理可能就需要大家去仔细研究了,我是讲不明白的,(:笑哭)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有