知乎问题 编程中什么是「Context(上下文)」 已经能够简单地说明什么是 Context,它是一个程序需要的外部对象,类似于一个全局变量。而这个变量的值会根据提供的值而改变。
Flask 中有分为请求上下文和应用上下文:
对象 | Context类型 | 说明 |
---|---|---|
current_app | AppContext | 当前的应用对象 |
g | AppContext | 处理请求时用作临时存储的对象 |
request | RequestContext | 请求对象,封装了Http请求的内容 |
session | RequestContext | 用于存储请求之间需要记住的值 |
Flask 分发请求之前激活程序请求上下文,请求处理完成后再将其删除。
Flask 中的 Context 是通过栈来实现。
Flask 的 Context 实现
Flask 的核心功能依赖于 Werkzeug 库。
_app_ctx_stack & _request_ctx_stack
这两种栈定义在 flask/global.py
中。
1 2 |
_request_ctx_stack = LocalStack() _app_ctx_stack = LocalStack() |
首先需要了解一下 Werkzeug 中关于 LcoalStack
的相关内容。
Local
类
Local
是定义了一个 __storage__
字典,其中的键为 thread
的 id
值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Local(object): __slots__ = ('__storage__', '__ident_func__') def __init__(self): object.__setattr__(self, '__storage__', {}) object.__setattr__(self, '__ident_func__', get_ident) def __setattr__(self, name, value): ident = self.__ident_func__() storage = self.__storage__ try: storage[ident][name] = value except KeyError: raise AttributeError(name) ... |
LocalStack
类
LocalStack
则内部维护一个 Local
实例。主要的作用是将 Local
维护的 __storage__
字典中键为 __ident_func__()
对应的值定义为 {"stack" : [] }
。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class LocalStack(object): def __init__(self): self._local = Local() def push(self, obj): rv = getattr(self._local, 'stack', None) if rv is None: self._local.stack = rv = [] rv.append(obj) return rv def pop(self, obj): pass |
LocalProxy
类
LocalProxy
类是一个代理类,应用到设计模式当中的代理模式。简单地讲,我们不需要去了解当前的环境,而直接去操作这个 Proxy
类,这个 Proxy
类会将所有的操作反馈给正确的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class LocalProxy(object): __slots__ = ('__local', '__dict__', '__name__') def __init__(self, local, name=None): object.__setattr__(self, '_LocalProxy__local', local) object.__setattr__(self, '__name__', name) def _get_current_object(self): # 通过此方法获取被代理的对象 if not hasattr(self.__local, '__release_local__') return self.__local try: return gerattr(self.__local,self.__name__) except Attribute: raise RuntimeError('no object bound to %s' % self.__name__) ... # 其他操作 |
request & RequestContext
Flask 源码中关于 request
的定义: