1. 程式人生 > >flask-Local源碼流程解析

flask-Local源碼流程解析

pmo get_id exc 源碼 [] nbsp gree ESS func

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源碼流程解析