app.run()的执行流程
1.首先来看最简单的一个flask应用。app是Flask类的实例,最后执行了app的run方法。
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函数。
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多路复用技术,后续会提到)。
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处理。
这里注意传入的三个参数: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的实例化方法,在其父类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__方法,又回到最开始的地方了。
所以,最终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)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。