Werkzeug之Local、LocalStack和LocalProxy

在我们使用Flask以及Werkzeug框架的过程中,经常会遇到如下三个概念:Local、LocalStack和LocalProxy。尤其在学习Flask的Request Context和App Context的过程中,这几个概念出现的更加频繁,另外很多Flask插件都会使用这三个概念对应的技术。那么这三个东西到底是什么?我们为什么需要它们?以及如何使用呢?本篇文章主要就是来解答这些问题。

Local

这部分我们重点介绍Local概念,主要分为以下几个部分:

  • 为什么需要Local?
  • Local的使用
  • Local的实现

为什么需要Local?

在Python的标准库中提供了thread local对象用于存储thread-safethread-specific的数据,通过这种方式存储的数据只在本线程中有效,而对于其它线程则不可见。正是基于这样的特性,我们可以把针对线程全局的数据存储进thread local对象,举个简单的例子

>>from threading import local
>>thread_local_data = local()
>>thread_local_data.user_name="Jim"
>>thread_local_data.user_name
'Jim'

使用thread local对象虽然可以基于线程存储全局变量,但是在Web应用中可能会存在如下问题:

  1. 有些应用使用的是greenlet协程,这种情况下无法保证协程之间数据的隔离,因为不同的协程可以在同一个线程当中。
  2. 即使使用的是线程,WSGI应用也无法保证每个http请求使用的都是不同的线程,因为后一个http请求可能使用的是之前的http请求的线程,这样的话存储于thread local中的数据可能是之前残留的数据。

为了解决上述问题,Werkzeug开发了自己的local对象,这也是为什么我们需要Werkzeug的local对象

Local的使用

先举一个简单的示例:

from werkzeug.local import Local, LocalManager

local = Local()
local_manager = LocalManager([local])

def application(environ, start_response):
    local.request = request = Request(environ)
    ...

# make_middleware会确保当request结束时,所有存储于local中的对象的reference被清除
application = local_manager.make_middleware(application)
  • 首先Local对象需要通过LocalManager来管理,初次生成LocalManager对象需要传一个list类型的参数,list中是Local对象,当有新的Local对象时,可以通过local_manager.locals.append()来添加。而当LocalManager对象清理的时候会将所有存储于locals中的当前context的数据都清理掉
  • 上例中当local.request被赋值之后,其可以在当前context中作为全局数据使用
  • 所谓当前context(the same context)意味着是在同一个greenlet(如果有)中,也就肯定是在同一个线程当中

那么Werkzeug的Local对象是如何实现这种在相同的context环境下保证数据的全局性和隔离性的呢?

Local的实现

我们先来看下源代码

# 在有greenlet的情况下,get_indent实际获取的是greenlet的id,而没有greenlet的情况下获取的是thread id
try:
    from greenlet import getcurrent as get_ident
except ImportError:
    try:
        from thread import get_ident
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值