文章目錄
-
-
-
-
-
- 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函數(無關源碼已删減),關鍵注意這裡是傳入了
,代表傳入了目前Flask類的執行個體。然後繼續檢視run_simple,run_simple實際是執行了其内部定義的inner函數。self
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執行個體)
。make_server函數實際是傳回BaseWSGIServer的執行個體然後執行其内部的serve_forrever方法。這裡的BaseWSGIServer即一個本地的server程式,預設是request_handler(None值)
的。單程序單線程
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
是BaseWSGIServer自身的執行個體。self
- 而這個ReuqustHandlerClass是什麼?看BaseWSGIServer類__init__方法中這句代碼:HTTPServer.
(self, server_address, handler),就知道,ReuqustHandlerClass即是WSGIRequestHandler這個類。__init__
- 這裡總結成一句話,就是請求到來時,會将請求傳給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
對應上面提到的BaseWSGIServer自身的執行個體。server
-
當請求到來時,執行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
,即Flask執行個體。而execute方法中執行app(environ, start_response),是對象()的形式。這裡會調用Flask執行個體的self
方法,于是又回到最開始的地方了。__call__