1.首先來看最簡單的一個flask應用。app是Flask類的實例,最後執行了app的run方法。python
from flask import 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函數。flask
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.inner函數調用make_server函數,注意這裏傳入的主要的4個值:hostname、port、application(即Flask實例)、request_handler(None值)。make_server函數實際是返回BaseWSGIServer的實例而後執行其內部的serve_forrever方法。這裏的BaseWSGIServer即一個本地的server程序,默認是單進程單線程的(可是使用了IO多路複用技術,後續會提到)。app
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源碼。注意,這裏涉及到多個類繼承,關係有點複雜。首先看方法的調用關係。serve_forever方法是執行的HTTPServer的serve_forever方法,而HTTPServer.serve_forever是調用自身的 _handle_request_noblock方法(這裏使用的IO多路複用技術),而_handle_request_noblock方法調用自身的process_request方法來接收請求,process_request將收到的請求交由finish_request方法處理。最終,交給RequestHandlerClass處理。socket
這裏注意傳入的三個參數:request、client_address、self。self是BaseWSGIServer自身的實例。ide
而這個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的實例化方法,在其父類BaseRequestHandler中,找到了實例化方法,果真,是在實例化方法時,執行自身的handle方法,來處理請求。debug
這裏注意實例化傳入的三個參數:request、client_address、server。server對應上面提到的BaseWSGIServer自身的實例。code
注意,這裏有點繞,仔細看。當請求到來時,執行handle方法,而handle方法已被WSGIRequestHandler重寫,重寫後的handle方法執行BaseHTTPRequestHandler的handle方法,實際是執行handle_one_request方法,而handle_one_request又被WSGIRequestHandler重寫,重寫後的handle_one_request實際是執行自身的run_wsgi方法。因此,請求的最終處理就在這裏。server
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__方法,又回到最開始的地方了。
因此,最終app.run()所執行的流程,都在這裏了。下一節我會繼續分享,請求的處理過程。
class WSGIRequestHandler(BaseHTTPRequestHandler, object): def run_wsgi(self): """處理request""" def write(data): pass def start_response(status, response_headers, exc_info=None): pass 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() try: execute(self.server.app) except Exception: """錯誤處理""" pass def handle(self): try: BaseHTTPRequestHandler.handle(self) except (_ConnectionError, socket.timeout) as e: self.connection_dropped(e) except Exception as e: if self.server.ssl_context is None or not is_ssl_error(e): raise if self.server.shutdown_signal: self.initiate_shutdown() def handle_one_request(self): self.raw_requestline = self.rfile.readline() if not self.raw_requestline: self.close_connection = 1 elif self.parse_request(): return self.run_wsgi() class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): def handle_one_request(self): pass def handle(self): self.close_connection = True self.handle_one_request() while not self.close_connection: self.handle_one_request() class StreamRequestHandler(BaseRequestHandler): pass class BaseRequestHandler: def __init__(self, request, client_address, server): self.request = request self.client_address = client_address self.server = server self.setup() try: self.handle() finally: self.finish() def handle(self): pass
class Flask(_PackageBoundObject): 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)