1.0 app启动后,浏览器发送请求触发app.call()方法
#1. 执行__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)
2.0 wsgi_app方法详解
def wsgi_app(self, environ, start_response):
# 2.1创建请求上下文ctx = RequestContext对象
ctx = self.request_context(environ)
error = None
try:
try:
# 2.20 创建应用上下文 app_ctx = AppContext对象,
# 2.21 将应用上下文维护成一个栈
# 2.22 将请求上下文维护成一个栈
# 2.23 创建session
# 2.24 路由匹配
ctx.push()
# 2.30 触发所有的@app.before_first_request,只有启动程序后,
# 第一个请求到来时执行
# 2.31 执行所有的@app.before_request,有返回值则直接返回给用户,不执行
# 下面的操作,无返回值则继续执行
# 2.32 执行所有的视图函数
# 2.33 执行所有的@app.after_request,
# 2.34 保存session
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except: # noqa: B001
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
# 2.4 销毁ctx/app_ctx
ctx.auto_pop(error)
2.1 创建请求上下文ctx = RequestContext对象
# 实例化ResquestContext对象
class Flask():
def request_context(self, environ):
return RequestContext(self, environ)
# 封装request和session
class RequestContext(object):
def __init__(self, app, environ, request=None, session=None):
self.app = app
if request is None:
request = app.request_class(environ)
self.request = request
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
2.20~24 ctx.push()方法
def push(self):
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc)
# Before we push the request context we have to ensure that there
# is an application context.
app_ctx = _app_ctx_stack.top
# 创建应用上下文 app_ctx = AppContext对象
if app_ctx is None or app_ctx.app != self.app:
app_ctx = self.app.app_context()
*********************************************************
class Flask():
def app_context(self):
return AppContext(self)
*********************************************************
# 2.21 调用app_ctx对象的push方法,将应用上下文维护成一个栈
app_ctx.push()
$$$$$$$$$$$$$$$$$$$$$$$app_ctx.push()过程$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
class AppContext():
...
def push(self):
self._refcnt += 1
if hasattr(sys, "exc_clear"):
sys.exc_clear()
# 2.211执行LocalStack实例化对象.push 方法
_app_ctx_stack.push(self)
appcontext_pushed.send(self.app)
# flask/globals.py文件
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, "request"))
session = LocalProxy(partial(_lookup_req_object, "session"))
g = LocalProxy(partial(_lookup_app_object, "g"))
# 2.212 将其维护成一个—_local(Local())的一个栈
class LocalStack():
def push(self, obj):
"""Pushes a new item to the stack"""
rv = getattr(self._local, "stack", None)
if rv is None:
self._local.stack = rv = []
rv.append(obj)
return rv
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
self._implicit_app_ctx_stack.append(app_ctx)
else:
self._implicit_app_ctx_stack.append(None)
if hasattr(sys, "exc_clear"):
sys.exc_clear()
# 2.22 将请求上下文维护成一个栈,同应用请求文一样
_request_ctx_stack.push(self)
# 2.23 创建session
if self.session is None:
session_interface = self.app.session_interface
self.session = session_interface.open_session(self.app, self.request)
if self.session is None:
self.session = session_interface.make_null_session(self.app)
# 2.24 路由匹配
if self.url_adapter is not None:
self.match_request()
2.30~2.32 response = self.full_dispatch_request()
def full_dispatch_request(self):
# 2.30 触发所有的@app.before_first_request,只有启动程序后,
# 第一个请求到来时执行.
self.try_trigger_before_first_request_functions()
########################################################
def try_trigger_before_first_request_functions(self):
if self._got_first_request:
return
with self._before_request_lock:
if self._got_first_request:
return
for func in self.before_first_request_funcs:
func()
self._got_first_request = True
########################################################
try:
request_started.send(self)
# 2.31 执行所有的@app.before_request,有返回值则直接返回给用户,不执行
# 下面的操作,无返回值则继续执行.
rv = self.preprocess_request()
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
def preprocess_request(self):
funcs = self.before_request_funcs.get(None, ())
if bp is not None and bp in self.before_request_funcs:
funcs = chain(funcs, self.before_request_funcs[bp])
for func in funcs:
rv = func()
if rv is not None:
return rv
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if rv is None:
# 2.32 执行所有的视图函数
rv = self.dispatch_request()
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
def dispatch_request(self):
return self.view_functions[rule.endpoint](**req.view_args)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
except Exception as e:
rv = self.handle_user_exception(e)
#2.33~2.34
return self.finalize_request(rv)
2.33~2.34 self.finalize_request(rv)
def finalize_request(self, rv, from_error_handler=False):
response = self.make_response(rv)
try:
# 2.33 执行所有的@app.after_request,
response = self.process_response(response)
request_finished.send(self, response=response)
except Exception:
if not from_error_handler:
raise
self.logger.exception(
"Request finalizing failed with an error while handling an error"
)
return response
# 遍历_after_request_functions,执行所有的after_request
def process_response(self, response):
ctx = _request_ctx_stack.top
bp = ctx.request.blueprint
funcs = ctx._after_request_functions
if bp is not None and bp in self.after_request_funcs:
funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
if None in self.after_request_funcs:
funcs = chain(funcs, reversed(self.after_request_funcs[None]))
for handler in funcs:
response = handler(response)
# 2.34 保存session
if not self.session_interface.is_null_session(ctx.session):
self.session_interface.save_session(self, ctx.session, response)
return response
2.4 ctx.auto_pop(error)>>>>销毁ctx/app_ctx
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:
# 2.41 ctx 销毁
self.pop(exc)
def pop(self, exc=_sentinel):
......
finally:
# 2.42ctx 执行LocalStack()的pop方法
rv = _request_ctx_stack.pop()
if clear_request:
rv.request.environ["werkzeug.request"] = None
# 2.43 执行app_ctx的pop方法,
if app_ctx is not None:
app_ctx.pop(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class AppContext():
def pop(self, exc=_sentinel):
....
finally:
# 2.44 执行LocalStack()的pop方法
rv = _app_ctx_stack.pop()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.42/2.44执行LocalStack的pop方法
*******************************************
# flask/globals.py文件
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
*******************************************
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:
release_local(self._local)
return stack[-1]
else:
return stack.pop()