Flask源码关于local的实现
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的实现的更多相关文章
- flask 源码专题(十一):LocalStack和Local对象实现栈的管理
目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于localstack的实现 3. 总结 04 LocalS ...
- 04 flask源码剖析之LocalStack和Local对象实现栈的管理
04 LocalStack和Local对象实现栈的管理 目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于l ...
- 线程锁、threading.local(flask源码中用的到)、线程池、生产者消费者模型
一.线程锁 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue 线程不安全 + 人(锁) => 排队处理 1.RLock/Lock:一次放一个 a.创建10个线 ...
- 用尽洪荒之力学习Flask源码
WSGIapp.run()werkzeug@app.route('/')ContextLocalLocalStackLocalProxyContext CreateStack pushStack po ...
- flask 源码剖析
flask 上下文管理源码流程及涉及的部分技术点 [flask源码梳理]之一 偏函数_mro [flask源码梳理]之二 面向对象中__setattr__ [flask源码梳理]之三 Local ...
- Flask源码剖析详解
1. 前言 本文将基于flask 0.1版本(git checkout 8605cc3)来分析flask的实现,试图理清flask中的一些概念,加深读者对flask的理解,提高对flask的认识.从而 ...
- 浅谈flask源码之请求过程
更新时间:2018年07月26日 09:51:36 作者:Dear. 我要评论 这篇文章主要介绍了浅谈flask源码之请求过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随 ...
- flask源码系列
更新中 HTML文档中元素存在,但是在浏览器中不显示.一般用于配合JavaScript代码使用. 04 LocalStack和Local对象实现栈的管理 05 Flask源码之:配置加载 06 Fla ...
- flask 源码专题(九):flask扩展点
1. 信号(源码) 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作. pip3 install blinker 2. 根据flask项目的请求流程来进行设置扩展点 中间件 # ...
随机推荐
- Numpy的学习4-array的合并
import numpy as np A = np.array([1, 1, 1]) B = np.array([2, 2, 2]) print(np.vstack((A, B))) # vertic ...
- Windows下python+allure的下载、安装、配置与使用
下载安装allure 1.Windows和mac均可选择从官网下载,下载地址: https://repo.maven.apache.org/maven2/io/qameta/allure/allure ...
- NET 5 爬虫框架/抓取数据
爬虫大家或多或少的都应该接触过的,爬虫有风险,抓数需谨慎. 爬虫有的是抓请求,有的是抓网页再解析 本着研究学习的目的,记录一下在 .NET Core 下抓取数据的实际案例.爬虫代码一般具有时效性,当 ...
- C#中获取DataTable某一列的值转换为集合
直接使用 //Linqvar l1 = (from d in dt.AsEnumerable() select d.Field<int>("ID")).ToList() ...
- JAVA递归算法及经典递归例子 对于这个汉诺塔问题
前言:递归(recursion):递归满足2个条件 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 第一题:汉诺塔 对于这个汉诺塔问题,在写递归时,我们只需要确定两个条件: ...
- Redis基础篇(五)AOF与RDB比较和选择策略
RDB和AOF对比 关于RDB和AOF的优缺点,官网上面也给了比较详细的说明redis.io/topics/pers- RDB 优点: RDB快照是一个压缩过的非常紧凑的文件,保存着某个时间点的数据集 ...
- Linux课程知识点总结(二)
Linux课程知识点总结(二) 七.Shell实用功能 7.1 命令行自动补全 在Linux系统中,有太多的命令和文件名称需要记忆,使用命令行补全功能[Tab]可以快速的写出文件名和命令名 7.2 命 ...
- 【WPF】 问题总结-RaidButton修改样式模板后作用区域的变化
最近工作需要,需要重绘RaidButton控件,具体想要达成的的效果是这样的: 当点击按钮任意一个地方的时候,按钮的背景改变. 于是我是这样对控件模板进行修改的: <Style x:Key=&q ...
- Java学习日报7.21
package leap;import java.util.Scanner;public class Leap {public static void main(String args[]) { in ...
- 2020年Python文章盘点,我选出了个人TOP10
大家好,我是猫哥.2020年过得真快啊!总感觉这一年里还没有做成多少事,一眨眼就又到了写年度总结的时候了-- 去年1月1日的时候,我写了<我的 2019 年 Python 文章榜单>,简单 ...