flask-Local源码流程解析
flask中Local源码数据类型
首先明确:源码中要构造的数据类型数是这样的:
__storage__ = {
用线程或者协程的唯一标识为键: {stack:[ctx(session/request) ,]}
}
其次源码用Local类构造数据类型,然后又用LocalStack类,作用是操作Local,让我们使用起来更方便,
LocalStack类中封装了push方法,用来给调用Local添加数据,pop方法取数据, 下面来看看具体代码怎么实现的
Local类构造数据类型
#用线程或者协程的唯一标识为键,
try:
# 协程唯一标识
from greenlet import getcurrent as get_ident
except:
# 进程唯一标识
from threading import get_ident class Local(object):
# __slots__设置只允许调用的属性
__slots__ = ('__storage__', '__ident_func__') def __init__(self):
# __storage__ = {1231:{'stack':[]}}
object.__setattr__(self, '__storage__', {}) #__storage__={}
object.__setattr__(self, '__ident_func__', get_ident) #__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):
# name=stack
# value=[]
#self对象调用属性
ident = self.__ident_func__() #get_ident()
storage = self.__storage__ #storage={}
try:
storage[ident][name] = value #storage={get_ident():{stack:[]}}
except KeyError:
storage[ident] = {name: value}
#删除数据
def __delattr__(self, name):
try:
del self.__storage__[self.__ident_func__()][name]
except KeyError:
raise AttributeError(name) #调用测试
obj = Local()
obj.stack = []
obj.stack.append('胖虎')
obj.stack.append('咸鱼')
print(obj.stack)
print(obj.stack.pop())
print(obj.stack)
"""
数据构造结果:
__storage__ = {
12312: {stack:[]}
} """
LocalStack类操作Local
# LocalStack 操作Local的类,让我们用起来更方法
class LocalStack(object):
def __init__(self):
# 以Local对象作为属性
self._local = Local()
# 向Local放值
def push(self,value):
# 会先执行Local类里面的__setattr__(self, name, value)方法,存储数据
rv = getattr(self._local, 'stack', None) # self._local.stack =>local.getattr
if rv is None:
self._local.stack = rv = [] # self._local.stack =>local.setattr
rv.append(value) # self._local.stack.append(666)
return rv #调用local取数据
def pop(self):
"""Removes the topmost item from the stack, will return the
old value or `None` if the stack was already empty.
"""
stack = getattr(self._local, 'stack', None)
if stack is None:
return None
elif len(stack) == 1:
return stack[-1]
else:
return stack.pop()
#
def top(self):
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None
最终实例化LocalStack类为_request_ctx_stack
通过_request_ctx_stack对象来操作Local,然后把ctx.request / ctx.session放到Local数据类型中
#实例化
_request_ctx_stack = LocalStack() _request_ctx_stack.push(RequestContext()) def _lookup_req_object(arg): ctx = _request_ctx_stack.top() return getattr(ctx,arg) # ctx.request / ctx.session #把request和session都封装到了Local中
request = functools.partial(_lookup_req_object,'request')
session = functools.partial(_lookup_req_object,'session')
flask-Local源码流程解析的更多相关文章
- Django生命周期 URL ----> CBV 源码解析-------------- 及rest_framework APIView 源码流程解析
一.一个请求来到Django 的生命周期 FBV 不讨论 CBV: 请求被代理转发到uwsgi: 开始Django的流程: 首先经过中间件process_request (session等) 然后 ...
- Rest Framework源码流程解析
目录: 一 整体流程 二 具体流程 一 请求进来之后,都要先执行dispatch方法,dispatch方法根据请求方式的不同触发get/post/put/delete等方法 注意,APIView中的d ...
- Flask信号源码流程
1. appcontext_pushed = _signals.signal('appcontext-pushed'# 请求app上下文push时执行 return RequestContext(se ...
- rest_framework解析器组件源码流程
rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...
- Flask源码流程分析(一)
Flask源码流程分析: 1.项目启动: 1.实例化Flask对象 1. 重要的加载项: * url_rule_class = Rule * url_map_class = Map * session ...
- Flask 源码流程,上下文管理
源码流程 创建对象 from flask import Flask """ 1 实例化对象 app """ app = Flask(__na ...
- mybatis 3.x源码深度解析与最佳实践(最完整原创)
mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...
- ES6.3.2 index操作源码流程
ES 6.3.2 index 操作源码流程 client 发送请求 TransportBulkAction#doExecute(Task,BulkRequest,listener) 解析请求,是否要自 ...
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go 的I/O 多路复用 netpoll),提供了 goroutine-per- ...
随机推荐
- (1)centos7 安装与分区
xxxxx 系统运行级别 /etc/inittab #
- UVA 11178 Morley's Theorem (坐标旋转)
题目链接:UVA 11178 Description Input Output Sample Input Sample Output Solution 题意 \(Morley's\ theorem\) ...
- ajaxFileUpload.js插件支持多文件上传的方法
前提条件:ajaxFileUpload.js插件多文件上传步骤:1.修改源码,(源码只支持单个文件的上传):复制代码 代码如下: //修改前代码------- //var oldElement = j ...
- 设置单网卡双ip
环境如下: [root@localhost ~]# cat /etc/redhat-releaseCentOS Linux release 7.7.1908 (Core) 安装时选择的最小化安装 -- ...
- 三(2)、springcloud之Eureka集群配置
1)原理说明** 服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会 ...
- 2018湘潭大学程序设计竞赛【E】
题目链接:https://www.nowcoder.com/acm/contest/105/E 题意:给你美食种类和查询次数,告诉你美味度和价格,给你固定钱数,问你最多能吃到多少美味度的食物.(X真是 ...
- PyQt5初识
学习PyQt5是个机缘,那是因为我的linux16.04+python3.6使了浑身解数也装不上PyQt4! PyQt5的官方文档貌似是要钱的!又想快速了解这个东东,我还是借鉴了万能的博客园大佬博主: ...
- js 正则替换的使用方法
function compress(source) { const keys = {}; ⇽--- 存储目标key source.replace( /([^=&]+)=([^&]*)/ ...
- android中的Handler消息传输机制
android平台不允许Activity新启动的线程访问该Activity里的界面组件,这样就导致新启动的线程无法动态的改变界面组件的属性值.但是实际android应用开发中,需要新启动的线程周期性地 ...
- leetcode-158周赛-5222-分割字符串
题目描述: 自己的提交: class Solution: def balancedStringSplit(self, s: str) -> int: if not s:return 0 res ...