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__,

最新文章

  1. UIApplication和OpenUrl的基于使用方法
  2. UDS(ISO14229-2006) 汉译(No.1 范围)
  3. redhat7下配置tomcat7,更改端口8080后无法访问页面
  4. BizTalk动手实验(三)BizTalk开发综合实验
  5. iScroll滚动区域中select、input、textarea元素无法点击的Bug修复
  6. MapReduce:详解Shuffle过程(转)
  7. js--题目二
  8. wcf Svcutil用法
  9. php url字符转义操作
  10. php静态属性和静态方法
  11. Nhibernate初入门基本配置(二)
  12. Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) B. Divisiblity of Differences
  13. [日志分析] Access Log 日志分析
  14. 工程造价数据服务云平台(造价BIM)
  15. 【转录组入门】6:reads计数
  16. Oracle课程档案,第十天
  17. bzoj2595 / P4294 [WC2008]游览计划
  18. css3中的BFC,IFC,GFC和FFC
  19. Toolbar 工具栏 菜单 标题栏 Menu
  20. 关于eclipse连接外置android模拟器

热门文章

  1. 工具-Git与GitHub-GitHub使用(99.5.3)
  2. Python——元组的基本语法(创建、访问、修改、删除)
  3. prim algorithm
  4. Linux下通用二进制方式安装MySQL
  5. [.NET] - 在Socket编程中遇到的问题总结
  6. Hyperledger fabric 链码篇GO(四)
  7. Vitis AI--个人调试篇
  8. 处理xls文件
  9. 图解HTTP权威指南(三)| Web服务器对HTTP请求的处理和响应
  10. Redis学习笔记之数据库(一)