虽然python
提供的有threadlocal
但是在web开发中:
1.使用greenlet
时,无法保证协程时间的数据隔离,因为不同的协程在一个线程中
2.wsgi
无法保证每个http请求使用的是不同线程,因为最后一个http请求可能使用的是前一个http请求的线程,所以可能用到threadlocal
中的残留数据
因此Werkzeug
开发了自己的local
对象.
1.支持协程
2.localstack
是对local
的二次封装数据结构不再是字典而是栈
当有新的请求的时候,会生成新的请求上下文,并且压入(push)栈,这样栈顶永远都是存储的当前请求的上下文,并且localstack提供了一个top方法可以让我们取到这个栈顶对象,但我们的请求结束的时候,会调拥pop方法,将请求上下文移除栈,这样就保证了文并发的情况下,实现了请求上下文的效果
from werkzeug.local import Local, LocalManager
local = Local()
local_manager = LocalManager([local])
def application(environ, start_response):
local.request = request = Request(environ)
...
application = local_manager.make_middleware(application)
这边代码将requests
和localrequest
绑定,其他的在当前上下文的代码都可以安全的访问local.request
,将获得相同的request object
werkzeug.local.release_local(local)
析构当前的context,这样就不需要使用manager
>>> loc = Local()
>>> loc.foo = 42
>>> release_local(loc)
>>> hasattr(loc, 'foo')
False
class werkzeug.local.LocalManager(locals=None, ident_func=None)
class werkzeug.local.LocalStack
>>> ls = LocalStack()
>>> ls.push(42)
>>> ls.top
42
>>> ls.push(23)
>>> ls.top
23
>>> ls.pop()
23
>>> ls.top
42
class werkzeug.local.LocalProxy(local, name=None)
werkzeug local
的代理,将所有的操作传给代理的对象.
from werkzeug.local import Local
l = Local()
# these are proxies
request = l('request')
user = l('user')
from werkzeug.local import LocalStack
_response_local = LocalStack()
# this is a proxy
response = _response_local()
创建一个proxies,可以向上面的方式,也可以用
session = LocalProxy(lambda: get_current_request().session)
参考:
https://werkzeug.palletsprojects.com/en/1.0.x/local/
参考:
https://www.jianshu.com/p/3f38b777a621
https://blog.csdn.net/caca95/article/details/82790550