天天看点

flask源码解析之app.run()的执行流程

文章目录

            • 1. 最简单的flask应用
            • 2. run方法的执行过程:
            • 3. make_server函数
            • 4. BaseWSGIServer
            • 5. WSGIRequestHandler

1. 最简单的flask应用

  • app是Flask类的实例,最后执行了app的run方法。
from flask import Flask

# app是Flask类的实例
app = Flask(__name__)

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

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

2. run方法的执行过程:

  • run实际是执行了werkzeug.serving的run_simple函数(无关源码已删减),关键注意这里是传入了

    self

    ,代表传入了当前Flask类的实例。然后继续查看run_simple,run_simple实际是执行了其内部定义的inner函数。
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
    from werkzeug.serving import run_simple
    try:
        run_simple(host, port, self, **options)
    finally:
        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,
):

    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()

    if use_reloader:
        run_with_reloader(inner, extra_files, reloader_interval, reloader_type)
    else:
        inner()
           

3. make_server函数

  • inner函数调用make_server函数,注意这里传入的主要的4个值:

    hostname

    port

    application(即Flask实例)

    request_handler(None值)

    。make_server函数实际是返回BaseWSGIServer的实例然后执行其内部的serve_forrever方法。这里的BaseWSGIServer即一个本地的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,
):
    """Create a new server instance that is either threaded, or forks
    or just processes one request after another.
    """
    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
        )
           

4. BaseWSGIServer

  • 请拿起你的小本本~重点来了!

    来看BaseWSGIServer源码。注意,这里涉及到多个类继承,关系有点复杂。首先看方法的调用关系。serve_forever方法是执行的HTTPServer的serve_forever方法,而HTTPServer.serve_forever是调用自身的 _handle_request_noblock方法(这里使用的IO多路复用技术),而_handle_request_noblock方法调用自身的process_request方法来接收请求,process_request将收到的请求交由finish_request方法处理。最终,交给RequestHandlerClass处理。这里注意传入的三个参数:

    request

    client_address

    self

    self

    是BaseWSGIServer自身的实例。
  • 而这个ReuqustHandlerClass是什么?看BaseWSGIServer类__init__方法中这句代码:HTTPServer.

    __init__

    (self, server_address, handler),就知道,ReuqustHandlerClass即是WSGIRequestHandler这个类。
  • 这里总结成一句话,就是请求到来时,会将请求传给WSGIRequestHandler这个类,进行实例化。而相应处理请求就只能在WSGIRequestHandler类中的

    __init__

    方法中了呀!
class BaseWSGIServer(HTTPServer, object):

    """Simple single-threaded, single-process WSGI server."""

    def __init__(
        self,
        host,
        port,
        app,
        handler=None,
        passthrough_errors=False,
        ssl_context=None,
        fd=None,
    ):
        if handler is None:
            handler = WSGIRequestHandler

        HTTPServer.__init__(self, server_address, handler)

        self.app = app

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


class HTTPServer(socketserver.TCPServer):
    pass


class TCPServer(BaseServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        BaseServer.__init__(self, server_address, RequestHandlerClass)


class BaseServer:
    def __init__(self, server_address, RequestHandlerClass):
        """Constructor.  May be extended, do not override."""
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False


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

                while not self.__shutdown_request:
                    ready = selector.select(poll_interval)
                    # bpo-35017: shutdown() called during select(), exit immediately.
                    if self.__shutdown_request:
                        break
                    if ready:
                        self._handle_request_noblock()

                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()


    def _handle_request_noblock(self):
        try:
            request, client_address = self.get_request()
        except OSError:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)
            except Exception:
                self.handle_error(request, client_address)
                self.shutdown_request(request)
            except:
                self.shutdown_request(request)
                raise
        else:
            self.shutdown_request(request)


    def process_request(self, request, client_address):
        self.finish_request(request, client_address)
        self.shutdown_request(request)


    def finish_request(self, request, client_address):
        """Finish one request by instantiating RequestHandlerClass."""
        self.RequestHandlerClass(request, client_address, self)
           

5. WSGIRequestHandler

  • 接着看WSGIRequestHandler这个类的代码,这里又涉及到复杂的继承关系。首先看WSGIRequestHandler的实例化方法,在其父类BaseRequestHandler中,找到了实例化方法,果然,是在实例化方法时,执行自身的handle方法,来处理请求。这里注意实例化传入的三个参数:

    request

    client_address

    server

    server

    对应上面提到的BaseWSGIServer自身的实例。
  • 重难点来了~

    当请求到来时,执行handle方法,而handle方法已被WSGIRequestHandler重写,重写后的handle方法执行BaseHTTPRequestHandler的handle方法,实际是执行handle_one_request方法,而handle_one_request又被WSGIRequestHandler重写,重写后的handle_one_request实际是执行自身的run_wsgi方法。所以,请求的最终处理就在这里。
  • run_wsgi方法实际是执行内部定义的execute方法,此时传入的是self.server.app。self.server对应的是BaseWSGIServer的实例,而.app就是一开始run_simple(host, port, self,

    **options

    )传入的

    self

    ,即Flask实例。而execute方法中执行app(environ, start_response),是对象()的形式。这里会调用Flask实例的

    __call__

    方法,于是又回到最开始的地方了。