什么是 Local

  1. wsgi 每次请求,会把过程进行抽离无状态话,过程数据存储在本次请求的全局变量中,使用到了Local. Local 作为每次请求的全局命令空间,属于每次请求的私有
  2. LocalStack 与 Local 相似,在 Local 基础之上使用堆栈方式进行操作,管理
  3. 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 获取的!

如:werkzeug.local.Local.py

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获取

这样使用有什么好处

  1. 支持底层协程操作,提高扩展并发效率
  2. 避免整个应用对请求上下文的管理与传递
  3. 扩展兼容性perfect,实现了对第三方应用的插拔式扩展
  4. 可阅读性强,操作使用简单,易上手

flask 中的 werkzeug Local,LocalStack 和 LocalProxy 技术应用的更多相关文章

  1. 利用Flask中的werkzeug.security模块加密

    1.这种加密方式的原理:加密时混入一段"随机"字符串(盐值)再进行哈希加密.即使 密码相同,如果盐值不同,那么哈希值也是不一样的.现在网站开发中主要是运 用这种加密方法. 2.这个 ...

  2. Flask中的请求上下文和应用上下文

    在Flask中处理请求时,应用会生成一个“请求上下文”对象.整个请求的处理过程,都会在这个上下文对象中进行.这保证了请求的处理过程不被干扰.处理请求的具体代码如下: def wsgi_app(self ...

  3. werkzeug(flask)中的local,localstack,localproxy探究

    1.关于local python中有threading local处理方式,在多线程环境中将变量按照线程id区分 由于协程在Python web中广泛使用,所以threading local不再满足需 ...

  4. Flask之Local、LocalStack和LocalProxy

    在我们使用Flask以及Werkzeug框架的过程中,经常会遇到如下三个概念:Local.LocalStack和LocalProxy.尤其在学习Flask的Request Context和App Co ...

  5. Flask(3)- flask中的CBV、werkzeug+上下文初步解读、偏函数和线程安全

    一.flask中的CBV 对比django中的CBV,我们来看一下flask中的CBV怎么实现? from flask import Flask, render_template, url_for, ...

  6. 04 flask源码剖析之LocalStack和Local对象实现栈的管理

    04 LocalStack和Local对象实现栈的管理 目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于l ...

  7. Flask中全局变量的实现

    我们都知道在Flask中g,request,session和request是作为全局对象来提供信息的,既然是全局的又如何保持线程安全呢,接下来我们就看看flask是如何做到这点的.在源码中的ctx.p ...

  8. 深入flask中的request

    缘起 在使用flask的时候一直比较纳闷request是什么原理,他是如何保证多线程情况下对不同请求参数的隔离的. 准备知识 在讲request之前首先需要先理解一下werkzeug.local中的几 ...

  9. flask中的上下文_请求上下文和应用上下文

    前引 在了解flask上下文管理机制之前,先来一波必知必会的知识点. 面向对象双下方法 首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__.__getattr__系列.__get ...

随机推荐

  1. 微信小程序封装自定义弹窗

    最近在做小程序的登录,需要同时获取用户手机号和头像昵称等信息,但是小程序又不支持单个接口同时获取两种数据,因此想到自定义一个弹窗,通过弹窗按钮触发获取手机号事件.记录一下. 具体代码如下: 业务代码中 ...

  2. Ant design在vue,react的引入

    文章地址: https://www.cnblogs.com/sandraryan/ 最近由于 一些不可描述的原因 要研究一下Ant design这个前端框架. 祭上官网: https://ant.de ...

  3. title与h1的区别、b与strong的区别、i与em的区别?

    title与h1的区别 定义: title是网站标题, h1是文章主题 作用: title概括网站信息,可以直接告诉搜索引擎和用户这 个网站是关于什么主题和内容的,是显示在网页Tab栏里的: h1突出 ...

  4. 2001年NOIP普及组复赛题解

    题目涉及算法: 数的计算:动态规划: 最大公约数和最小公倍数问题:质因数分解: 求先序排列:递归: 装箱问题:动态规划(纯0-1背包问题) 数的计算 题目链接:https://www.luogu.or ...

  5. Windows Community Toolkit 3.0 新功能 在WinForms 和 WPF 使用 UWP 控件

    本文告诉大家一个令人震惊的消息,Windows Community Toolkit 有一个大更新,现在的版本是 3.0 .最大的提升就是 WinForm 和 WPF 程序可以使用部分 UWP 控件. ...

  6. javaObject类

    所有类的公共父类,一旦一个类没有显示地继承一个类则其直接父类一定是Object. 一切数据类型都可用Object接收 class OOXX  extends Object{}等价于class ooXX ...

  7. python 字符串方法isdigit()

    python isdigit() 方法检测字符串是否只有数字组成. 语法: isdigit()方法语法: str.isdigit() 参数:无 返回值: 如果字符串中只含有数字则返回True,否则返回 ...

  8. 记录vue创建项目过程

    已经学过无数次,但是每次都忘记,毕竟脑容量太小了,每次都需要翻看原来项目和视频再次学习,所以以此文字形式记录下来,方便于下次使用观看 1.打开git,找到创建vue的文件夹(已经安装好git的,然后在 ...

  9. 2019-8-31-C#-await-高级用法

    title author date CreateTime categories C# await 高级用法 lindexi 2019-08-31 16:55:58 +0800 2018-2-13 17 ...

  10. 2018-2-13-win10-uwp-图标制作器

    title author date CreateTime categories win10 uwp 图标制作器 lindexi 2018-2-13 17:23:3 +0800 2018-2-13 17 ...