您的位置:首页 > 产品设计 > UI/UE

flask之源码解读RequestContext(请求上下文)执行流程

2018-01-05 20:30 603 查看

流程分析:

# 这里会调用Flask.__call__(self, environ, start_response)
app = Flask(__name__)

if __name__=='__main__':
app.run()

def __call__(self, environ, start_response):
"""Shortcut for :attr:`wsgi_app`."""
return self.wsgi_app(environ, start_response)

# 接着返回一个对象,这里去执行,我们看下这个:
def wsgi_app(self, environ, start_response):
# 关键代码
ctx = self.request_context(environ)
#返回的上下文对象放到哪里去了呢?我们看下push方法:
ctx.push()
# 处理请求:
try:
#这里去分发request,处理request
finally:
#当请求结束:
ctx.auto_pop(error)

#我们看下ctx = self.request_context(environ)做了什么?
def request_context(self, environ):
#返回了请求的上下文对象,那么ctx 代表请求的上下文对象
return RequestContext(self, environ)

#ctx.push()调用的push方法
class RequestContext(object):
def push(self):
# 这里将自己加入了_request_ctx_stack,
#那么_request_ctx_stack是个什么鬼?
_request_ctx_stack.push(self)

#在globals.py文件中可以看到:
_request_ctx_stack = LocalStack()

#那么LocalStack 中的都有什么呢?
class LocalStack(object):
def __init__(self):
#接着我们看下local是个啥?
self._local = Local()
def push(self, obj):
# push方法的作用将新的item压栈,这里看到self._local
"""Pushes a new item to the stack"""
rv = getattr(self._local, 'stack', None)
if rv is None:
#现在的字典是这样的:{'当前线程的唯一标识':{'stack':[]}}
self._local.stack = rv = []
# 请求进来将请求上下文RequestContext加入到列表中:
rv.append(obj)
return rv

#接着我们看下local是个啥?self._local = Local()
class Local(object):
def __init__(self):
# 看这是创建了空字典
object.__setattr__(self, '__storage__', {})
#这是干什么的呢?看下get_ident
object.__setattr__(self, '__ident_func__', get_ident)

def __setattr__(self, name, value):
#触发get_ident的运行
ident = self.__ident_func__()
storage = self.__storage__
try:
#那么这句话构造了一个字典,key便是当前线程的标识,代表了当前线程。形如:
#{'当前线程标识':{name:value}},那么回去我们再看上面:self._local.stack = rv = []
storage[ident][name] = value

except KeyError:
storage[ident] = {name: value}

#get_ident 是干什么用的呢?
def get_ident(): # real signature unknown; restored from __doc__
"""
get_ident() -> integer
#翻译一下:返回一个能唯一标识当前线程和其它共存线程的非零integer!!!
Return a non-zero integer that uniquely identifies the current thread
amongst other threads that exist simultaneously /saɪmlˈteɪniəsli/.
This may be used to identify per-thread resources.
Even though on some platforms threads identities may appear to be
allocated consecutive numbers starting at 1, this behavior should not
be relied upon, and the number should be seen purely as a magic cookie.
A thread's identity may be reused for another thread after it exits.
"""
return 0

#当请求结束,执行ctx.auto_pop(error)
def auto_pop(self, exc):
if self.request.environ.get('flask._preserve_context') or \
(exc is not None and self.app.preserve_context_on_exception):
self.preserved = True
self._preserved_exc = exc
else:
# 直接将当前的请求上下文pop掉
self.pop(exc)

#最终调用self.pop(exc):
def pop(self, exc=_sentinel):
#翻译一下:将请求上下文弹栈,并解绑!
"""Pops the request context and unbinds it by doing that.  This will
also trigger the execution of functions registered by the
:meth:`~flask.Flask.teardown_request` decorator.

.. versionchanged:: 0.9
Added the `exc` argument.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python