flask源碼分析,run函數啓動分析

對flask背後運行機制感興趣,參考網上資料,結合源碼分析run函數運行時的機制,主要整理出函數調用棧。以flask0.1分析flask

首先
Flask官方文檔經典示例 hello.pyapp

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

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

如今來分析app.run()啓動時發生了什麼? # 代碼只列出用到的函數,去掉註釋等
flask.pysocket

class Flask(object):

  def run(self, host='localhost', port=5000, **options):
       
        from werkzeug import run_simple
        if 'debug' in options:
            self.debug = options.pop('debug')
        options.setdefault('use_reloader', self.debug)
        options.setdefault('use_debugger', self.debug)
        return run_simple(host, port, self, **options)

run函數導入from werkzeug import run_simple 運行run_simple(host, port, self, **options)函數

werkzeug/serving.py源碼分析

def run_simple(hostname, port, application, use_reloader=False, extra_files=None, threaded=False, processes=1):
    
    def inner():
        srv = make_server(hostname, port, application, threaded,
                          processes)
        try:
            srv.serve_forever()
        except KeyboardInterrupt:
            pass
    inner()

run_simple函數主要運行inner(),inner調用make_server()返回類,而後調用返回類的serve_forever()。先來看看make_server()spa

werkzeug/serving.pydebug

ddef make_server(host, port, app=None, threaded=False, processes=1):
    
    if threaded and processes > 1:
        raise ValueError("cannot have a multithreaded and "
                         "multi process server.")
    elif threaded:
        class handler(BaseRequestHandler):
            multithreaded = True
        class server(ThreadingMixIn, WSGIServer):
            pass
    elif processes > 1:
        class handler(BaseRequestHandler):
            multiprocess = True
            max_children = processes - 1
        class server(ForkingMixIn, WSGIServer):
            pass
    else:
        handler = BaseRequestHandler
        server = WSGIServer
    srv = server((host, port), handler)
    srv.set_app(app)
    return srv

make_server(hostname, port, application, threaded, processes) 傳入的都是默認參數,起做用的代碼是code

else:
        handler = BaseRequestHandler
        server = WSGIServer
    srv = server((host, port), handler)
    srv.set_app(app)
    return srv

能夠看出srv = server((host, port), handler) ,其實就是srv = WSGIServer((host, port), BaseRequestHandler),返回類就是WSGIServer ,綁定BaseRequestHandler。先看WSGIServer server

wsgiref/simple_server.py繼承

class WSGIServer(HTTPServer):
  def __init__=  標準庫 BaseHTTPServer.py  class HTTPServer(SocketServer.TCPServer) : #WSGIServer繼承HTTPServer的__init__函數,它本身沒有 ,這句是我加的方便理解 ,下同

  def set_app(self,application):    #這個就是make_server函數中調用的 set_app
        self.application = application
  def get_app(self):            #
        return self.application

標準庫 BaseHTTPServer.py  
class HTTPServer(SocketServer.TCPServer) 
  def __init__=  標準庫 SocketServer.py class TCPServer(BaseServer):


標準庫 SocketServer.py 
class TCPServer(BaseServer):
   def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:         # 這裏調用socket.socket綁定端口
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

class BaseServer:
    def __init__(self, server_address, RequestHandlerClass):
        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):    #這個就是run_simple中調用的serve_forever
        
        self.__is_shut_down.clear()
        try:
            while not self.__shutdown_request:
                
                r, w, e = _eintr_retry(select.select, [self], [], [],
                                       poll_interval)
                if self in r:
                    self._handle_request_noblock()   #調用serve_forever時調用_handle_request_noblock
        finally:
            self.__shutdown_request = False

            self.__is_shut_down.set()
    def _handle_request_noblock(self):   
       
        try:
            request, client_address = self.get_request()
        except socket.error:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)  #繼續
            except:
                self.handle_error(request, client_address)
                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):
        self.RequestHandlerClass(request, client_address, self)    # #繼續 並參見 werkzeug/serving.py  make_server()

調用serve_forever後到了self.RequestHandlerClass(request, client_address, self) ,根據前面的代碼可知RequestHandlerClass 就是werkzeug/serving.py中的BaseRequestHandler,繼續

class BaseRequestHandler(WSGIRequestHandler):
    def __init__=  標準庫 wsgiref/simple_server.py class WSGIRequestHandler(BaseHTTPRequestHandler): #這句跟前面同樣繼承父類   
    

wsgiref/simple_server.py

class WSGIRequestHandler(BaseHTTPRequestHandler):
    def __init__=  標準庫 BaseHTTPServer.py class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): #繼續父類

BaseHTTPServer.py
class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
    def __init__=  標準庫 SocketServer.py  class StreamRequestHandler(BaseRequestHandler):  #繼續父類


SocketServer.py

class StreamRequestHandler(BaseRequestHandler):
 #繼續父類

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()   # 運行  參見 werkzeug/serving.py  class BaseRequestHandler.handle
        finally:
            self.finish()

最後運行了self.handle() 參見 werkzeug/serving.py class BaseRequestHandler.handle
前面有,再貼下看看

class BaseRequestHandler(WSGIRequestHandler):
   def handle(self):     #一、調用的就是這個handle,覆蓋了父類的handle 
        self.raw_requestline = self.rfile.readline()
        if self.parse_request():
            self.get_handler().run(self.server.get_app())  #二、調用 get_handler()後,還繼續調用 run() ,get_app就是wsgiref/simple_server.py中WSGIServer類定義的函數   

    def get_handler(self):  # 三、看看它返回了什麼
        handler = self._handler_class
        if handler is None:
            class handler(ServerHandler):  #四、新建一個類 返回的就是這個類 ,繼承ServerHandler
              '''   
                  五、直接從其餘文件copy出所需代碼,也就是handler的父類
                   wsgiref/simple_server.py  class ServerHandler(SimpleHandler): 繼續父類 
                   wsgiref/handlers.py  
                       class SimpleHandler(BaseHandler):
                          def __init__(self,stdin,stdout,stderr,environ,multithread=True, multiprocess=False ):
                              self.stdin = stdin
                              self.stdout = stdout
                              self.stderr = stderr
                              self.base_env = environ
                              self.wsgi_multithread = multithread
                              self.wsgi_multiprocess = multiprocess
                       class BaseHandler:  #六、調用的就是這個類的run函數
                                  def run(self, application):
                                    try:
                                        self.setup_environ()
                                        self.result = application(self.environ, self.start_response)   #七、調用app,也就是app=Flask() Flask類的 __call__
                                        self.finish_response()
                                    except:
                                          try:
                                               self.handle_error()
                                          except:
                                             # If we get an error handling an error, just give up already!
                                             self.close()
                                             raise   # ...and let the actual server figure it out.


                 '''
                wsgi_multithread = self.multithreaded                      
                wsgi_multiprocess = self.multiprocess
            self._handler_class = handler

        rv = handler(self.rfile, self.wfile, self.get_stderr(),
                     self.get_environ())
        rv.request_handler = self
        return rv

能夠看出最後調用的是application(self.environ, self.start_response) 這個application就是開始的app = Flask(__name__),調用類就是調用類的__call__ 函數 ,繼續貼一下源碼

class Flask(object):

   def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

   def wsgi_app(self, environ, start_response):
        
        with self.request_context(environ):
            rv = self.preprocess_request()
            if rv is None:
                rv = self.dispatch_request()
            response = self.make_response(rv)
            response = self.process_response(response)
            return response(environ, start_response)

OK,大功告成,最後調用wsgi_app(self, environ, start_response)函數,這個就是返回響應的主函數了!!

從整個流程中,flask利用WSGIServer類啓動監聽端口並綁定,BaseRequestHandler類接收、返回相應的信息!徹底符合WSGI要求。剩餘的工做就太過於底層,很差深刻分析了。也畫了調用流程圖,不過太大很差傳,若是有須要能夠繼續交流!

相關文章
相關標籤/搜索