• 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')
    
    
  • 相关阅读:
    CentOS 6.4 x64 zabbix 2.2.2 编译安装
    Monitorix 监控 安装配置
    CentOS 6.4 x64 Percona-Server-5.6.15 源码安装
    CentOS 6.4 x64 安装 配置 Redmine 2.4.1
    ActiviMQ的基本使用
    Java内存 模型理解
    线程池的两种创建方式及区别
    线程创建的三种方式及区别
    Spring cloud 之Ribbon(二)负载均衡原理
    Spring cloud 之Ribbon(一)基本使用
  • 原文地址:https://www.cnblogs.com/zzy-9318/p/9193392.html
Copyright © 2020-2023  润新知