入口
if __name__ == "__main__":
app.run()
进入run
中:
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
# self = app = FLask对象
往下翻:
from werkzeug.serving import run_simple
try:
run_simple(host, port, self, **options)
# self = app = FLask对象
run
实际执行的就是run_simple
,就是app加括号(对象加括号),最终执行__call__
方法,回到入口,app应该有一个__call__
方法:
if __name__ == "__main__":
app.run()
app.__call__()
现在我们正式进入Flask的请求上下文环节,首先点击进入__call__
方法中:
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
# self = app = FLask对象
# environ 请求的原始信息 里面包括请求头、请求体等
# start_response response对象
run
本质执行的j就是wsgi_app
,回到入口,app应该有一个wsgi_app
方法:
if __name__ == "__main__":
app.run()
app.__call__()
app.wsgi_app()
点击进入wsgi_app
方法中:
def wsgi_app(self, environ, start_response): # self = app = FLask对象
"""The actual WSGI application. This is not implemented in
:meth:`__call__` so that middlewares can be applied without
losing a reference to the app object. Instead of doing this::
app = MyMiddleware(app)
往下翻,找到:
ctx = self.request_context(environ)
error = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
点击进入到request_context
中:
def request_context(self, environ): # self = app = FLask对象
"""Create a :class:`~flask.ctx.RequestContext` representing a
WSGI environment. Use a ``with`` block to push the context,
which will make :data:`request` point at this request.
......
"""
return RequestContext(self, environ)
# self = app = FLask对象
# environ 请求的原始信息 里面包括请求头、请求体等
点击进入到RequestContext
中:
#app = FLask对象=self
#那还有一个self是什么呢,往上翻,这个self是RequestContext
# environ 请求的原始信息 里面包括请求头、请求体等
def __init__(self, app, environ, request=None, session=None):
self.app = app
if request is None:
request = app.request_class(environ) # 序列化请求信息,变成Flask可用的格式
self.request = request # self=RequestContext=request_context
self.url_adapter = None
try:
self.url_adapter = app.create_url_adapter(self.request)
except HTTPException as e:
self.request.routing_exception = e
self.flashes = None
self.session = session
所有完整的request的值都在这里进行序列化,主要记着这里有了request与session就行,其它不用管,再回到ctx
:
ctx = self.request_context(environ)
# ctx = request_context,其中包含上面的request与session
error = None
try:
try:
ctx.push() # request_context.push()
response = self.full_dispatch_request()
进入到push
中:
def push(self): # self = ctx = request_context=(request,session)
"""Binds the request context to the current context."""
# If an exception occurs in debug mode or if context preservation is
# activated under exception situations exactly one context stays
往下翻,找到:
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc)
进入到_request_ctx_stack
中:
# context locals
_request_ctx_stack = LocalStack()
# _request_ctx_stack 请求上下文栈,实例化LocalStack(),执行__init__方法
进入到LocalStack
中:
def __init__(self):
self._local = Local() # 实例化Local,执行__init__方法
进入到Local
中:
class Local(object):
__slots__ = ("__storage__", "__ident_func__") # 节省内存,实例只能使用这些属性
def __init__(self):
object.__setattr__(self, "__storage__", {})
object.__setattr__(self, "__ident_func__", get_ident)
#由于使用了__slots__优化内存 ,实例是通过数组来构建的,不是字典的形式
#Local大概是[{},get_ident],属性名在内部会映射到数组小标中
再回到上面,就是说:
def __init__(self):
self._local = Local() # 实例化Local,执行__init__方法
# self._local = Local=[{},get_ident]
再回到这里:
# context locals
_request_ctx_stack = LocalStack()
# _request_ctx_stack 请求上下文栈,实例化LocalStack(),执行__init__方法
# _request_ctx_stack.._local = Local=[{},get_ident]
再往回翻,翻到push
这里:
def push(self): # self = ctx = request_context=(request,session)
"""Binds the request context to the current context."""
# If an exception occurs in debug mode or if context preservation is
# activated under exception situations exactly one context stays
往下走,找到top
:
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc)
进入top
中:
def top(self):
"""The topmost item on the stack. If the stack is empty,
`None` is returned.
"""
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None
# __slots__ = ("__storage__", "__ident_func__") # 节省内存,实例只能使用这些属性
# 由上面知道,_local只能有两个属性,这里报错,最后返回None
再回到上面:
top = _request_ctx_stack.top # None
# _request_ctx_stack._local=[{},get_ident]
if top is not None and top.preserved:
top.pop(top._preserved_exc)
往下翻,找到这句:
_request_ctx_stack.push(self)
# self = ctx = request_context=(request,session)
进入到push中:
def push(self, obj): # obj= ctx = request_context=(request,session)
"""Pushes a new item to the stack"""
# 这个self往上找,self._local = Local=[{},get_ident]
rv = getattr(self._local, "stack", None)
if rv is None:
self._local.stack = rv = []
# _local对象.stack执行__setattr__方法
rv.append(obj)
return rv
进入到_local
中找到__setattr__
方法:
def __setattr__(self, name, value):
ident = self.__ident_func__() # 获取线程或协程id 假设为9528
storage = self.__storage__ # storage={}
try:
storage[ident][name] = value # 不成立 没有name
except KeyError:
storage[ident] = {name: value} # storage={9528:{name:value}}
核心
再回到上面的push
中:
def push(self, obj): # obj= ctx = request_context=(request,session)
"""Pushes a new item to the stack"""
# 这个self往上找,self._local = Local=[{},get_ident]
rv = getattr(self._local, "stack", None)
if rv is None:
self._local.stack = rv = [] # {9528:{stack :[]}}
# _local对象.stack执行__setattr__方法
rv.append(obj)
# {9528:{stack :[ctx(request,session)]}}
return rv
到这里,一个存放请求信息的栈就形成了。你是9528,你进来后,生成一个stack,stack存放的就是9528的请求信息。你是9529,、9531等依次对应,所有用户的请求信息都是这样存储。
转载:https://blog.csdn.net/qq_35289736/article/details/106112256
查看评论