werkzeug LocalProxy

1.当我们代理的理解

from werkzeug.local import LocalStack, LocalProxy

l_stack = LocalStack()
l_stack.push({'name': 'wang'})
l_stack.push({'name': 'wei'})


def get_name():
    return l_stack.pop()

# 不用代理
name = get_name()
print(f"name is {name['name']}")
print(f"name is {name['name']}")

# 结果
# wang
# wang

l_stack = LocalStack()
l_stack.push({'name': 'wang'})
l_stack.push({'name': 'wei'})


# 代理操作get_name
name2 = LocalProxy(get_name)
print(f"{name2['name']}") # 每次使用name2获取属性,相当于调用一次get_name方法
print(f"{name2['name']}")

# 结果
# wang
# wei

2.flask框架正是使用了这个代理的特点,可以在全局中获得当前的上下文,比如current_app,request,sessiong

# context locals
_request_ctx_stack = LocalStack()
current_app = LocalProxy(lambda: _request_ctx_stack.top.app)
request = LocalProxy(lambda: _request_ctx_stack.top.request)
session = LocalProxy(lambda: _request_ctx_stack.top.session)
g = LocalProxy(lambda: _request_ctx_stack.top.g)

每次我们使用current_app时,都会从_request_ctx_stack.top.app的栈顶重新获取,如果不用代理

current_app = _request_ctx_stack.top.app

这样在调用current_app时则只会获得一次,而且以后都不会再改变

3.代理是如何实现的:

class LocalProxy(object):
# ... 省略部分代码
__getitem__ = lambda x, i: x._get_current_object()[i] # x是代理对象本身(上例中name2),i是要查询的属性

# 结合 __init__与 _get_current_object()方法来看。
class LocalProxy(object):
    __slots__ = ("__local", "__dict__", "__name__", "__wrapped__")

    def __init__(self, local, name=None):
        object.__setattr__(self, "_LocalProxy__local", local)
        object.__setattr__(self, "__name__", name)
        if callable(local) and not hasattr(local, "__release_local__"):
            object.__setattr__(self, "__wrapped__", local)

    def _get_current_object(self):
        if not hasattr(self.__local, "__release_local__"):
            return self.__local()
        try:
            return getattr(self.__local, self.__name__)
        except AttributeError:
            raise RuntimeError("no object bound to %s" % self.__name__)

参考:
https://zhuanlan.zhihu.com/p/103376446
https://www.cnblogs.com/daofaziran/p/10826357.html
https://www.cnblogs.com/flowell/p/local_local_proxy_local_stack.html
https://blog.csdn.net/weixin_38091140/article/details/93592079
https://segmentfault.com/a/1190000007663087
https://blog.tonyseek.com/post/the-context-mechanism-of-flask/
https://cizixs.com/2017/01/13/flask-insight-context/
https://werkzeug.palletsprojects.com/en/1.0.x/
https://www.cnblogs.com/caoxing2017/p/8282530.html
https://www.toptal.com/python/pythons-wsgi-server-application-interface
https://www.jianshu.com/p/995bd7ae463a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值