• 04 flask源码剖析之LocalStack和Local对象实现栈的管理


    04 LocalStack和Local对象实现栈的管理

    1.源码入口

    from flask import globals
    # 从globals进入可以看见此源码
    

    1. flask源码关于local的实现

    1. local与localstack关系

      • flask中是localstack结合local使用
      • local为localstack提供基本结构
    2. 源码实现

      try:
          # 协程
          from greenlet import getcurrent as get_ident
      except ImportError:
          try:
              from thread import 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)
      
          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)
      

    2. flask源码关于localstack的实现

    1. 两个localstack对象

      • 存储RequestContext相关,包括reqeust、session
      • 存储AppContenxt相关,包括app、g(所有app对象都包括在里边)
      _request_ctx_stack = LocalStack()
      __storage__ = {
      	1111:{'stack':[RequestContext(reqeust,session),]},
          1123:{'stack':[RequestContext(reqeust,session),]},
      }
      
      _app_ctx_stack = LocalStack()
      __storage__ = {
      	1111:{'stack':[AppContenxt(app,g),]}
          1123:{'stack':[AppContenxt(app,g),]},
      }
      
    2. localstack源码实现

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

    3. 总结

    • 在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()
      
    • flask上下文管理也是基于此

      • 请求上下文管理
      • 应用上下文管理

    image-20191124160342120

  • 相关阅读:
    悼念丹尼斯·里奇,那个给乔布斯提供肩膀的巨人(转载)
    c# 做成Windows服务
    Visual Studio 2010 新建完项目编译就出错
    C#调用Win32 的API函数User32.dll
    c# Remoting小例子
    backgroundworker使用 实现进度条ProgressBar
    winform最小化后隐藏到右下角,单击或双击后恢复
    关于Thread的实例
    c# 捕获的异常写到日志里
    C# delegate and event 规范写法
  • 原文地址:https://www.cnblogs.com/liubing8/p/11930180.html
Copyright © 2020-2023  润新知