flask 中的 werkzeug Local,LocalStack 和 LocalProxy 技术应用
什么是 Local
- wsgi 每次请求,会把过程进行抽离无状态话,过程数据存储在本次请求的全局变量中,使用到了Local. Local 作为每次请求的全局命令空间,属于每次请求的私有
- LocalStack 与 Local 相似,在 Local 基础之上使用堆栈方式进行操作,管理
- LocalProxy 代理类,代理 Local 或 LocalStack 实例
为什么使用 Local
为什么使用自定义 Local,而不是 threading.local。这是由内核决定的
1. web 应用在启动之后,是一单线+协成程启动的话,会污染全局变量,无法区分,
2. 使用多线程+协成无法保证,派发请求的工作协程,无法保证同时工作时且分别位于多个线程内,彼此互不影响
所以: werkzeug 给出了自己的解决方案:Local 和 LocalStack
为什么使用 LocalProxy
那么问题来了:请求的上下文的私有变量存储在 Local 和 LocalStack 中,那在多任务时,每次调用 from flask import request, g, session , 如何保证获取正确的上下文,而不发生混乱?
在 flask.globals.py 中
def _lookup_req_object(name):
top = _request_ctx_stack.top
if top is None:
raise RuntimeError('working outside of request context')
return getattr(top, name) _request_ctx_stack = LocalStack()
request = LocalProxy(partial(_lookup_req_object, 'request'))
session = LocalProxy(partial(_lookup_req_object, 'session'))
在 werkzeug.local.py 中, LocalProxy是一个 Local or LocalStack 的一个代理
@implements_bool
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__"):
# "local" is a callable that is not an instance of Local or
# LocalManager: mark it as a wrapped function.
object.__setattr__(self, "__wrapped__", local) def _get_current_object(self):
"""Return the current object. This is useful if you want the real
object behind the proxy at a time for performance reasons or because
you want to pass the object into a different context.
"""
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__) def __getattr__(self, name):
if name == "__members__":
return dir(self._get_current_object())
return getattr(self._get_current_object(), name)
调用 reqeust:动态 request <= 动态的 _request_ctx_stack.top <= LocalStack() 每次调用产生使用新的实例与方法结合(request)<= LoaclStack.call?
是的,每次调用 request,就会新产生一个proxy实例,每次pop, push, top 均是针对 Local 的操作,而 Local 的属性赋值与获取均是针对 get_ident 获取的!
class Local(object):
__slots__ = ("__storage__", "__ident_func__") def __init__(self):
object.__setattr__(self, "__storage__", {})
object.__setattr__(self, "__ident_func__", get_ident)
""""""
def __getattr__(self, name):
try:
return self.__storage__[self.__ident_func__()][name]
except KeyError:
raise AttributeError(name) def __setattr__(self, name, value):
ident = self.__ident_func__()
storage = self.__storage__
try:
storage[ident][name] = value
except KeyError:
storage[ident] = {name: value}
perfect!每次新请求来临时,flask 会把上下文存储在 werkzeug Local 中,使用时根据线程或者协程id获取
这样使用有什么好处
- 支持底层协程操作,提高扩展并发效率
- 避免整个应用对请求上下文的管理与传递
- 扩展兼容性perfect,实现了对第三方应用的插拔式扩展
- 可阅读性强,操作使用简单,易上手
flask 中的 werkzeug Local,LocalStack 和 LocalProxy 技术应用的更多相关文章
- 利用Flask中的werkzeug.security模块加密
1.这种加密方式的原理:加密时混入一段"随机"字符串(盐值)再进行哈希加密.即使 密码相同,如果盐值不同,那么哈希值也是不一样的.现在网站开发中主要是运 用这种加密方法. 2.这个 ...
- Flask中的请求上下文和应用上下文
在Flask中处理请求时,应用会生成一个“请求上下文”对象.整个请求的处理过程,都会在这个上下文对象中进行.这保证了请求的处理过程不被干扰.处理请求的具体代码如下: def wsgi_app(self ...
- werkzeug(flask)中的local,localstack,localproxy探究
1.关于local python中有threading local处理方式,在多线程环境中将变量按照线程id区分 由于协程在Python web中广泛使用,所以threading local不再满足需 ...
- Flask之Local、LocalStack和LocalProxy
在我们使用Flask以及Werkzeug框架的过程中,经常会遇到如下三个概念:Local.LocalStack和LocalProxy.尤其在学习Flask的Request Context和App Co ...
- Flask(3)- flask中的CBV、werkzeug+上下文初步解读、偏函数和线程安全
一.flask中的CBV 对比django中的CBV,我们来看一下flask中的CBV怎么实现? from flask import Flask, render_template, url_for, ...
- 04 flask源码剖析之LocalStack和Local对象实现栈的管理
04 LocalStack和Local对象实现栈的管理 目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于l ...
- Flask中全局变量的实现
我们都知道在Flask中g,request,session和request是作为全局对象来提供信息的,既然是全局的又如何保持线程安全呢,接下来我们就看看flask是如何做到这点的.在源码中的ctx.p ...
- 深入flask中的request
缘起 在使用flask的时候一直比较纳闷request是什么原理,他是如何保证多线程情况下对不同请求参数的隔离的. 准备知识 在讲request之前首先需要先理解一下werkzeug.local中的几 ...
- flask中的上下文_请求上下文和应用上下文
前引 在了解flask上下文管理机制之前,先来一波必知必会的知识点. 面向对象双下方法 首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__.__getattr__系列.__get ...
随机推荐
- C# Brush Color String 互相转换
using System.Windows.Media; //String转换成Color Color color = (Color)ColorConverter.ConvertFromString(s ...
- oracle等式比较和范围比较
当WHERE子句中有索引列, ORACLE不能合并它们,ORACLE将用范围比较. 举例: DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引. SELECT ENAME FROM ...
- HTML静态网页--JavaScript-Window.document对象
1.Window.document对象 一.找到元素: docunment.getElementById("id"):根据id找,最多找一个: var a =docunmen ...
- HDU1711 Number Sequence 题解 KMP算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 题目大意:最基础的字符串匹配,只不过这里用整数数组代替了字符串. 给你两个数组 \(a[1..N ...
- HDU 2844 混合背包、
题意:一个人想买手表,给你n个价值的硬币,然后给你n个价值硬币对应的个数.但是呢,这个人只知道这个手表的价格不超过m元.问他最多能买多少种价值的手表 思路:dp背包专题 但是- - 一直不知道该怎么d ...
- Java日志框架——JCL
JCL,全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging". 一.JCL原理 1.基本原理 JC ...
- 2018-2-13-win10-uwp-获取指定的文件-AQS
title author date CreateTime categories win10 uwp 获取指定的文件 AQS lindexi 2018-2-13 17:23:3 +0800 2018-2 ...
- dotnet core 使用 CoreRT 将程序编译为 Native 程序
现在微软有一个开源项目 CoreRT 能通过将托管的 .NET Core 编译为单个无依赖的 Native 程序 这个项目现在还没发布,但是能尝试使用,可以带来很多的性能提升 使用 CoreRT 发布 ...
- H3C MSTP
- 2019-5-21-win10-uwp-商业游戏-1.1.5
title author date CreateTime categories win10 uwp 商业游戏 1.1.5 lindexi 2019-05-21 11:38:20 +0800 2018- ...