app.run()执行过程1.先来看一个最简单的flask应用。app是Flask类的一个实例,最后执行的是app的run方法。fromflaskimportFlaskapp=Flask(__name__)@app.route('/')defindex():返回“helloworld!”if__name__=='__main__':app.run()2.看一下run方法的实现过程。可以看出run实际上是执行了werkzeug.serving的run_simple函数(无关源码已删除)。重点是这里传入了self,也就是传入了当前Flask类的实例。然后继续看run_simple,run_simple其实执行的是里面定义的inner函数。defrun(self,host=None,port=None,debug=None,load_dotenv=True,**options):fromwerkzeug.servingimportrun_simpletry:run_simple(host,port,self,**options)最后:self。_got_first_request=Falsedefrun_simple(主机名、端口、应用程序、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,):definner():try:fd=int(os.environ["WERKZEUG_SERVER_FD"])除了(LookupError,ValueError):fd=Nonesrv=make_server(hostname,port,application,threaded,processes,request_handler,passthrough_errors,ssl_context,fd=fd,)如果fd为None:log_startup(srv.socket)srv.serve_forever()ifuse_reloader:run_with_reloader(inner,extra_files,reloader_interval,reloader_type)else:inner()3.inner函数调用make_server函数,注意这里传递的主要4个值:hostname,port,application(即Flask实例),request_handler(Nonevalue)make_server函数实际上返回一个BaseWSGIServer的实例,然后执行其内部的serve_forrever方法。这里的BaseWSGIServer是一个本地服务器程序,默认是单进程单线程的(但是使用了IO多路复用技术,后面会提到)。defmake_server(host=None,port=None,app=None,threaded=False,processes=1,request_handler=None,passthrough_errors=False,ssl_context=None,fd=None,):"""创建一个新的服务器实例要么是线程化的,要么是分叉的,或者只是一个接一个地处理请求。"""如果线程化且进程>1:引发ValueError("不能拥有多线程和多进程服务器。")elifthreaded:returnThreadedWSGIServer(host,port,app,request_handler,passthrough_errors,ssl_context,fd=fd)elif进程>1:returnForkingWSGIServer(host,port,app,processes,request_handler,passthrough_errors,ssl_context,fd=fd,)else:returnBaseWSGIServer(host,port,app,request_handler,passthrough_errors,ssl_context,fd=fd)4.重点来了!来看看BaseWSGISe在rver源码中注意,这里涉及到多个类的继承,关系有点复杂。先看方法的调用关系。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__方法中啊!classBaseWSGIServer(HTTPServer,object):"""简单的单线程、单进程的WSGI服务器。"""def__init__(self,host,port,app,handler=None,passthrough_errors=False,ssl_context=None,fd=None,):如果处理程序为None:handler=WSGIRequestHandlerHTTPServer.__init__(self,server_address,handler)self.app=appdefserve_forever(self):self.shutdown_signal=Falsetry:HTTPServer.serve_forever(self)除了KeyboardInterrupt:最后通过:self.server_close()classHTTPServer(socketserver.TCPServer):passclassTCPServer(BaseServer):def__init__(self,server_address,RequestHandlerClass,bind_and_activate=True):"""Constructor.Maybeextended,donotoverride."""BaseServer.__init__(self,server_address,RequestHandlerClass)classBaseServer:def__init__(self,server_address,RequestHandlerClass):"""构造函数。可以扩展,不要覆盖。"""self.server_address=server_addressself.RequestHandlerClass=RequestHandlerClassself.__is_shut_down=threading.Event()self.__shutdown_request=Falsedefserve_forever(self,poll_interval=0.5):try:with_ServerSelector()asselector:selector.register(self,selectors.EVENT_READ)而不是self.__shutdown_request:ready=selector.select(poll_interval)#bpo-35017:shutdown()在select()期间调用,立即退出。如果self.__shutdown_request:如果准备就绪则中断:self._handle_request_noblock()self.service_actions()最后:self.__shutdown_request=Falseself.__is_shut_down.set()def_handle_request_noblock(self):try:request,client_address=self.get_request()exceptOSError:returnifself.verify_request(request,client_address):try:self.process_request(request,client_address)除了异常:self.handle_error(请求,client_address)self.shutdown_request(请求)除了:self.shutdown_request(请求)引发其他:self.shutdown_request(请求)defprocess_request(self,请求,client_address):self.finish_request(请求,client_address)self.shutdown_request(request)deffinish_request(self,request,client_address):"""通过实例化RequestHandlerClass完成一个请求。"""self.RequestHandlerClass(request,client_address,self)5.继续看WSGIRequestHandler这个类的代码,这里又浸又到复合的继承关系先看WSGIRequestHandler的实例化方法。在其父类BaseRequestHandler中,找到了实例化方法。果然在实例化方法的时候,执行了自己的handle方法来处理请求。这里注意实例化传入的三个参数:request、client_address、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方法中以object()的形式执行app(environ,start_response)。这里会调用Flask实例的__call__方法,我们又回到了开头。所以,最后,app.run()执行的流程都在这里了。下一节,我会继续分享请求处理过程。classWSGIRequestHandler(BaseHTTPRequestHandler,object):defrun_wsgi(self):"""处理请求"""defwrite(data):passdefstart_response(status,response_headers,exc_info=None):passdefexecute(app):application_iter=app(environ,start_response)try:fordatainapplication_iter:write(data)ifnotheaders_sent:write(b"")最后:ifhasattr(application_iter,"close"):application_iter.close()try:execute(self.server.app)exceptException:"""错误处理"""passdefhandle(self):try:BaseHTTPRequestHandler.handle(self)except(_ConnectionError,socket.timeout)ase:self.connection_dropped(e)exceptExceptionase:如果self.server.ssl_context是None或者不是is_ssl_error(e):raiseifself.server.shutdown_signal:self.initiate_shutdown()defhandle_one_request(self):self.raw_requestline=self.rfile.readline()如果不是self.raw_requestline:self.close_connection=1elifself.parse_request():返回self.run_wsgi()类BaseHTTPRequestHandler(socketserver.StreamRequestHandler):defhandle_one_request(self):通过defhandle(self):self.close_connection=Trueself.handle_one_request()而不是self.close_connection:self.handle_one_request()classStreamRequestHandler(BaseRequestHandler):passclassBaseRequestHandler:def__init__(self,request,client_address,server):self.request=requestself.client_address=client_addressself.server=serverself.setup()try:self.handle()最后:self.finish()def句柄(self):passclassFlask(_PackageBoundObject):def__call__(self,environ,start_response):"""WSGI服务器调用Flask应用程序对象作为WSGI应用程序。这调用:meth:`wsgi_app`可以包装到应用中间件."""返回self.wsgi_app(environ,start_response)
