Python3 Flask框架主流程源码分析(一)

Flask是一个使用Python编写的轻量级Web应用框架。基于Werkzeug WSGI工具箱和Jinja2模板引擎。Flask使用BSD授权。
Flask被称为“微框架”,因为它使用简单的核心,用扩展增加其他功能。Flask没有默认使用的数据库、窗体验证工具。然而,Flask保留了扩增的弹性,可以用Flask-extension加入这些功能:ORM、窗体验证工具、文件上传、各种开放式身份验证技术。
举个例子,一下是一个helloworld的简单demo:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():
    return 'hello'


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

我们先从第一个函数Flask开始看

def __init__(
    self,
    import_name,
    static_url_path=None,
    static_folder="static",
    static_host=None,
    host_matching=False,
    subdomain_matching=False,
    template_folder="templates",
    instance_path=None,
    instance_relative_config=False,
    root_path=None,
):

初始化函数中,static_folder="static"表示静态文件下载的默认目录,template_folder="templates"表示模板的默认目录。
我们继续往下看:


self.view_functions = {}
self.error_handler_spec = {}

self.before_request_funcs = {}
self.after_request_funcs = {}

view_functions表示视图函数保存的字典
error_handler_spec表示错误处理函数保存的字典
before_request_funcs表示request处理之前调用函数保存的字典
after_request_funcs 表示request处理之后调用函数保存的字典

之后我们再看@app.route(’/’)这个装饰器的函数

def route(self, rule, **options):
def decorator(f):
    endpoint = options.pop("endpoint", None)
    self.add_url_rule(rule, endpoint, f, **options)
    return f

	return decorator

继续进入add_url_rule这个函数

def add_url_rule(
    self,
    rule,
    endpoint=None,
    view_func=None,
    provide_automatic_options=None,
    **options
):
if endpoint is None:
    	endpoint = _endpoint_from_view_func(view_func)

因为第一次运行endpoint 为None所以进入_endpoint_from_view_func这个函数

def _endpoint_from_view_func(view_func):
    assert view_func is not None,
    return view_func.__name__

可以看到这个函数是返回函数的名称,因此endpoint此时的值为传入的函数名
最后通过

self.view_functions[endpoint] = view_func

将我们的处理函数放入视图处理函数的字典中

我们再看app.run()这个函数

def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
_host = "127.0.0.1"
_port = 5000
###
from werkzeug.serving import run_simple

	try:
    	run_simple(host, port, self, **options)
	finally:
    	self._got_first_request = False

可以看到如果不传入参数的话ip和port的默认值为127.0.0.1和5000,最后调用的是run_simple这个函数
我们继续看

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,
):
###
def inner():
    try:
        fd = int(os.environ["WERKZEUG_SERVER_FD"])
    except (LookupError, ValueError):
        fd = None
    srv = make_server(
        hostname,
        port,
        application,
        threaded,
        processes,
        request_handler,
        passthrough_errors,
        ssl_context,
        fd=fd,
    )
    if fd is None:
        log_startup(srv.socket)
    srv.serve_forever()

可以看到调用的是make_server函数得到对象后的serve_forever函数
我们接着看make_server函数

def make_server(
    host=None,
    port=None,
    app=None,
    threaded=False,
    processes=1,
    request_handler=None,
    passthrough_errors=False,
    ssl_context=None,
    fd=None,
):
###
    if threaded and processes > 1:
        raise ValueError("cannot have a multithreaded and multi process server.")
    elif threaded:
        return ThreadedWSGIServer(
            host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd
        )
    elif processes > 1:
        return ForkingWSGIServer(
            host,
            port,
            app,
            processes,
            request_handler,
            passthrough_errors,
            ssl_context,
            fd=fd,
        )
    else:
        return BaseWSGIServer(
            host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd
        )

可以看到这个函数支持1.多线程模式2.多进程模式3.普通模式(单线程)
继续看普通模式的serve_forever函数

def serve_forever(self):
    self.shutdown_signal = False
    try:
        HTTPServer.serve_forever(self)
    except KeyboardInterrupt:
        pass
    finally:
        self.server_close()

调用的是HTTPServer.serve_forever
继续往下看

def serve_forever(self, poll_interval=0.5):
###
with _ServerSelector() as selector:
    	selector.register(self, selectors.EVENT_READ)

    	while not self.__shutdown_request:
        	ready = selector.select(poll_interval)
        	if self.__shutdown_request:
           		 break
        	if ready:
            	self._handle_request_noblock()

        	self.service_actions()
###

可以看到调用的是selector.select函数,而selector是从_ServerSelector这个对象中来的

if hasattr(selectors, 'PollSelector'):
    _ServerSelector = selectors.PollSelector
else:
    _ServerSelector = selectors.SelectSelector

最后我们可以确认调用的是poll这个函数做为http server的IO模型。

想知道后面是如何调用到视图函数的可以看我的下一篇文章。(https://blog.csdn.net/sinat_27016095/article/details/115056887 link

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页