Flask启动原理,源码流程分析

时间:2021-09-06 22:13:02

1.执行Flask的实例对象.run()方法

from flask import Flask,request,session

app = Flask(__name__)

app.secret_key ='sdfsdfsdf'

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

2.经过对IP与端口的处理,然后执行 from werkzeug.serving import run_simple中的 run_simple(host, port, self, **options)方法

    def run(self, host=None, port=None, debug=None, **options):

        from werkzeug.serving import run_simple
#查看是否有ip
if host is None:
host = '127.0.0.1'
if port is None:
# 读取settings文件
server_name = self.config['SERVER_NAME']
# print(server_name)#127.0.0.1:80
if server_name and ':' in server_name:
port = int(server_name.rsplit(':', 1)[1])
# print(port)#80
else:
port = 5000
if debug is not None:
self.debug = bool(debug)
print(self.debug)
options.setdefault('use_reloader', self.debug)
options.setdefault('use_debugger', self.debug)
try:
run_simple(host, port, self, **options)
finally:
# reset the first request information if the development server
# reset normally. This makes it possible to restart the server
# without reloader and that stuff from an interactive shell.
self._got_first_request = False
def run_simple(hostname, port, application, use_reloader=False,
use_debugger=False, use_evalex=True,
extra_files=None, reloader_interval=1,
reloader_type='auto', threaded=False,
processes=1, request_handler=None, static_files=None,
passthrough_errors=False, ssl_context=None):
"""Start a WSGI application. Optional features include a reloader,
multithreading and fork support. This function has a command-line interface too:: python -m werkzeug.serving --help .. versionadded:: 0.5
`static_files` was added to simplify serving of static files as well
as `passthrough_errors`. .. versionadded:: 0.6
support for SSL was added. .. versionadded:: 0.8
Added support for automatically loading a SSL context from certificate
file and private key. .. versionadded:: 0.9
Added command-line interface. .. versionadded:: 0.10
Improved the reloader and added support for changing the backend
through the `reloader_type` parameter. See :ref:`reloader`
for more information. :param hostname: The host for the application. eg: ``'localhost'``
:param port: The port for the server. eg: ``8080``
:param application: the WSGI application to execute
:param use_reloader: should the server automatically restart the python
process if modules were changed?
:param use_debugger: should the werkzeug debugging system be used?
:param use_evalex: should the exception evaluation feature be enabled?
:param extra_files: a list of files the reloader should watch
additionally to the modules. For example configuration
files.
:param reloader_interval: the interval for the reloader in seconds.
:param reloader_type: the type of reloader to use. The default is
auto detection. Valid values are ``'stat'`` and
``'watchdog'``. See :ref:`reloader` for more
information.
:param threaded: should the process handle each request in a separate
thread?
:param processes: if greater than 1 then handle each request in a new process
up to this maximum number of concurrent processes.
:param request_handler: optional parameter that can be used to replace
the default one. You can use this to replace it
with a different
:class:`~BaseHTTPServer.BaseHTTPRequestHandler`
subclass.
:param static_files: a list or dict of paths for static files. This works
exactly like :class:`SharedDataMiddleware`, it's actually
just wrapping the application in that middleware before
serving.
:param passthrough_errors: set this to `True` to disable the error catching.
This means that the server will die on errors but
it can be useful to hook debuggers in (pdb etc.)
:param ssl_context: an SSL context for the connection. Either an
:class:`ssl.SSLContext`, a tuple in the form
``(cert_file, pkey_file)``, the string ``'adhoc'`` if
the server should automatically create one, or ``None``
to disable SSL (which is the default).
"""

3.execute(app) 中 application_iter = app(environ, start_response)即call方法

        def execute(app):
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
if not headers_sent:
write(b'')
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None

4.call方法中返回 return self.wsgi_app(environ, start_response)

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

5.首先,处理的是request和session,将请求添加到Local中,即 ctx = self.request_context(environ)

    def wsgi_app(self, environ, start_response):

        #处理request,将请求添加到local中
ctx = self.request_context(environ)
# 处理request和session
ctx.push()
error = None
try:
try:
# 执行视图函数
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except:
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)

5.1.返回的是 return RequestContext(self, environ) 即类的一个实例

    def request_context(self, environ):

        return RequestContext(self, environ)

5.2.执行 ctx.push()方法 保存

    def push(self):
"""Binds the request context to the current context.""" 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
if app_ctx is None or app_ctx.app != self.app:
app_ctx = self.app.app_context()
app_ctx.push()
self._implicit_app_ctx_stack.append(app_ctx)
else:
self._implicit_app_ctx_stack.append(None) if hasattr(sys, 'exc_clear'):
sys.exc_clear() _request_ctx_stack.push(self) self.session = self.app.open_session(self.request)
if self.session is None:
self.session = self.app.make_null_session()

6.执行视图函数 response = self.full_dispatch_request()方法

    def full_dispatch_request(self):
"""Dispatches the request and on top of that performs request
pre and postprocessing as well as HTTP exception catching and
error handling. .. versionadded:: 0.7
"""
self.try_trigger_before_first_request_functions()
try:
request_started.send(self)
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()
except Exception as e:
rv = self.handle_user_exception(e)
return self.finalize_request(rv)

6.1:执行 self.try_trigger_before_first_request_functions()即装饰器@before_first_request装饰所有函数
6.2:执行 rv = self.preprocess_request()方法 即@before_request装饰所有函数
6.3:return self.finalize_request(rv)方法 即@after_request装饰所有函数
response = self.process_response(response)方法
# 执行after_request 装饰所有的函数 response = handler(response)
最后处理session self.save_session(ctx.session, response)

7.return response(environ, start_response) 将处理完的内容返回给用户浏览器