flask源码关于local的实现

try:
# 协程
from greenlet import getcurrent as get_ident
except ImportError:
try:
from thread import get_ident # 导入get_ident
except ImportError:
from _thread import get_ident
"""
__storage__ = {
1111:{"stack":[汪洋] }
}
"""
class Local(object): def __init__(self):
# self.__storage__ = {}
# self.__ident_func__ = get_ident
object.__setattr__(self, "__storage__", {})
object.__setattr__(self, "__ident_func__", get_ident) def __iter__(self):
return iter(self.__storage__.items()) def __release_local__(self):
self.__storage__.pop(self.__ident_func__(), None) # 由于get_ident是一个方法,当获取到这个对象之后需要加括号才能执行所以self.__ident_func__() 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__() # 1111
storage = self.__storage__
try:
storage[ident][name] = value
except KeyError:
storage[ident] = {name: value} def __delattr__(self, name):
try:
del self.__storage__[self.__ident_func__()][name]
except KeyError:
raise AttributeError(name) class LocalStack(object):
def __init__(self):
self._local = Local()
def push(self, obj):
"""Pushes a new item to the stack"""
# self._local.stack == getattr
# rv = None
rv = getattr(self._local, "stack", None)
if rv is None:
self._local.stack = rv = []
rv.append(obj)
return rv def pop(self):
stack = getattr(self._local, "stack", None)
if stack is None:
return None
elif len(stack) == 1:
# release_local(self._local)
# del __storage__[1111]
return stack[-1]
else:
return stack.pop() @property
def top(self):
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None obj = LocalStack()
obj.push('汪洋')
obj.push('成说') print(obj.top) obj.pop()
obj.pop()

总结:

在flask中有个local类,他和threading.local的功能一样,为每个线程开辟空间进行存取数据,他们两个的内部实现机制,内部维护一个字典,以线程(协程)ID为key,进行数据隔离,如:
__storage__ = {
1211:{'k1':123}
} obj = Local()
obj.k1 = 123 在flask中还有一个LocalStack的类,他内部会依赖local对象,local对象负责存储数据,localstack对象用于将local中的值维护成一个栈。
__storage__ = {
1211:{'stack':['k1',]}
} obj= LocalStack()
obj.push('k1')
obj.top
obj.pop()

7.flask源码中总共有2个localstack对象

# context locals
__storage__ = {
1111:{'stack':[RequestContext(reqeust,session),]},
1123:{'stack':[RequestContext(reqeust,session),]},
}
_request_ctx_stack = LocalStack() __storage__ = {
1111:{'stack':[AppContenxt(app,g),]}
1123:{'stack':[AppContenxt(app,g),]},
}
_app_ctx_stack = LocalStack()
_request_ctx_stack.push('小魔方')
_app_ctx_stack.push('大魔方')
  • 上下文管理

    • 请求上下文管理
    • 应用上下文管理

解析

1. 首先说请求上下文管理的设计思路:
* 当开启多线程或者协程去执行这个程序的时候,就需要对每个访问对象包装自己的数据,这样就不会发生数据的冲突,那么要怎么才能规避这个问题呢??
* 利用threading.local的知识,根据相似的实现原理,设计这个上下文管理机制;
* 首先写一个Local类,这个类中封装两个属性一个的属性值是一个空的字典,这个空字典的设计是这样的:字典中的键是当先执行的线程或者协程的id值,然后值是一个空的列表;
*另一个是get_ident方法名,这个方法是获取可以获取到线程或者协程的id;这个的内部是将协程的模块名改成:get_ident了,所以你如果开的是线程就获取线程的id,如果是协程就获取协程的id;
* 然后就是这个类中的实现方法了,有一个__setattr__方法,这个方法的作用主要是增加给__storage__这个字典中增加值的,__getattr__这个方法时获取这当前这线程或者协程值对应的id去__storage__获取对应的id的那个列表;
* 还有一个清空当前线程或者协程保存的数据__release_local__,

Flask源码关于local的实现的更多相关文章

  1. flask 源码专题(十一):LocalStack和Local对象实现栈的管理

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

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

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

  3. 线程锁、threading.local(flask源码中用的到)、线程池、生产者消费者模型

    一.线程锁 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue 线程不安全 + 人(锁) => 排队处理 1.RLock/Lock:一次放一个 a.创建10个线 ...

  4. 用尽洪荒之力学习Flask源码

    WSGIapp.run()werkzeug@app.route('/')ContextLocalLocalStackLocalProxyContext CreateStack pushStack po ...

  5. flask 源码剖析

    flask 上下文管理源码流程及涉及的部分技术点 [flask源码梳理]之一  偏函数_mro [flask源码梳理]之二  面向对象中__setattr__ [flask源码梳理]之三  Local ...

  6. Flask源码剖析详解

    1. 前言 本文将基于flask 0.1版本(git checkout 8605cc3)来分析flask的实现,试图理清flask中的一些概念,加深读者对flask的理解,提高对flask的认识.从而 ...

  7. 浅谈flask源码之请求过程

    更新时间:2018年07月26日 09:51:36   作者:Dear.   我要评论   这篇文章主要介绍了浅谈flask源码之请求过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随 ...

  8. flask源码系列

    更新中 HTML文档中元素存在,但是在浏览器中不显示.一般用于配合JavaScript代码使用. 04 LocalStack和Local对象实现栈的管理 05 Flask源码之:配置加载 06 Fla ...

  9. flask 源码专题(九):flask扩展点

    1. 信号(源码) 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作. pip3 install blinker 2. 根据flask项目的请求流程来进行设置扩展点 中间件 # ...

随机推荐

  1. JQuery ajax request及Java服务端乱码问题及设置

    今天花了半天功夫才搞定2个乱码问题 1. 原先一直用form提交,现在改作JQuery ajax 提交,发现乱码. 2. window.location url中含有中文提交后,乱码. 第一个问题: ...

  2. Numpy的学习5-array的分割

    import numpy as np A = np.arange(12).reshape((3, 4)) print(A) """ array([[ 0, 1, 2, 3 ...

  3. springMVC框架连接数据库查询数据

    1.框架搭建,创建一个maven项目打war包 web.xml文件 <?xml version="1.0" encoding="UTF-8"?> & ...

  4. Linux 时间同步 01 简介

    Linux 时间同步 01 简介 目录 Linux 时间同步 01 简介 时间同步 公共NTP服务器地址及IP 系统时间相关文件 时间同步 大数据产生与处理系统是各种计算设备集群的,计算设备将统一.同 ...

  5. 十、scala、spark集群搭建

    spark集群搭建: 1.上传scala-2.10.6.tgz到master 2.解压scala-2.10.6.tgz 3.配置环境变量 export SCALA_HOME=/mnt/scala-2. ...

  6. livy提交spark应用

      spark-submit的使用shell时时灵活性较低,livy作为spark提交的一种工具,是使用接口或者java客户端的方式提交,可以集成到web应用中 1.客户端提交的方式 http://l ...

  7. spark的 structStreaming 一些介绍

    转发 https://www.toutiao.com/a6696339998905467403/?tt_from=mobile_qq&utm_campaign=client_share& ...

  8. DHCP.md

    DHCP 主配置文件   从 /usr/share/doc/dhcp 复制 dhcpd.conf.sample 到/etc/dhcp下                                  ...

  9. Linux服务器下安装Composer 并使用Composer安装Thinkphp5.0

    Composer官方文档:https://docs.phpcomposer.com/00-intro.htmlComposer是一个php的包管理器.要求php版本在5.3以上. 一.安装Compos ...

  10. cookie和session会话技术

    因为http协议是无状态的,也就是说每个客户端访问服务器端资源时,服务器并不知道该客户端是谁,所以需要会话技术识别客户端状态.会话技术是帮助服务器记住客户端状态的. 一次会话的开始是通过浏览器访问某个 ...