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')

原文地址:https://www.cnblogs.com/zzy-9318/p/9193392.html