運行Flask其本質是運行Flask對象中的__call__,而__call__
本質調用wsgi_app的方法python
wsgi_app方法
flask
def wsgi_app(self, environ, start_response): #1.ctx是ResquestContext的對象,裏面request ctx = self.request_context(environ) error = None try: try: #2.就是ctx放到了Local對象 ctx.push() #3.全部請求的執行函數的,包括請求擴展,真正的視圖函數 response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: # noqa: B001 error = sys.exc_info()[1] raise #3. 請求以後的函數 return response(environ, start_response) finally: if self.should_ignore_error(error): error = None #4.最後把對應的request在request的隊列中刪除 ctx.auto_pop(error)
請求相關的,ctx如今是包含request,session的RequestContext的對象服務器
源碼
session
1.1RequestContext(self, environ) self ,是app對象 environ,請求相關的 1.2 RequestContext在實例化的時候的源碼: def __init__(self, app, environ, request=None, session=None): self.app = app if request is None: request = app.request_class(environ) self.request = request self.url_adapter = None try: self.url_adapter = app.create_url_adapter(self.request) except HTTPException as e: self.request.routing_exception = e self.flashes = None self.session = session self._implicit_app_ctx_stack = [] self.preserved = False self._after_request_functions = [] #這個RequestContext對象封裝了,request 和seesoin
這個ctx是RequestContext,那就執行RequestContext.push方法app
def push(self): #_request_ctx_stack是localStack的對象 #self是ctx,把self也就ctx放入到local對象裏面 top = _request_ctx_stack.top if top is not None and top.preserved: top.pop(top._preserved_exc) app_ctx = _app_ctx_stack.top if app_ctx is None or app_ctx.app != self.app: app_ctx = self.app.app_context() app_ctx.push() self._implicit_app_ctx_stack.append(app_ctx) else: self._implicit_app_ctx_stack.append(None) if hasattr(sys, "exc_clear"): sys.exc_clear() _request_ctx_stack.push(self) #這個裏面的push源碼以下 if self.session is None: session_interface = self.app.session_interface self.session = session_interface.open_session(self.app, self.request) if self.session is None: self.session = session_interface.make_null_session(self.app) if self.url_adapter is not None: self.match_request()
源碼中的push的源碼框架
#obj是ctx def push(self, obj): #obj是ctx,requestContext的對象 rv = getattr(self._local, "stack", None) if rv is None: self._local.stack = rv = [] rv.append(obj) return rv ''' 2.1.1 _request_ctx_stack.push(self)如今的self是ctx 2.1.2 _request_ctx_stack是LocalStack()的對象 2.1.3 LocalStack()的push把ctx傳過來 2.1.4 LocalStack()的push方法 最終也就是ctx.push()他的最終目的:把當前的ctx放入到Local()裏面 '''
源碼函數
#這是服務器第一次請求時候執行的函數 self.try_trigger_before_first_request_functions() try: request_started.send(self) #執行請求以前全部的函數,而且拿到請求以前的返回值 rv = self.preprocess_request() if rv is None: #這個是真正視圖函數,若是個人請求以前函數沒有返回值纔會執行 rv = self.dispatch_request() except Exception as e: rv = self.handle_user_exception(e) return self.finalize_request(rv) 3.1 return self.finalize_request(rv)的源碼: def finalize_request(self, rv, from_error_handler=False): response = self.make_response(rv) try: #請求以後的函數,after_request response = self.process_response(response) request_finished.send(self, response=response) except Exception: if not from_error_handler: raise self.logger.exception( "Request finalizing failed with an error while handling an error" ) return response
也解釋了爲何before_request有返回值後就不會運行真正的視圖,由於有返回值後rv就不爲空了就不運行下面的函數url
一樣咱們若是頂進去process_response的相關函數能夠看出來他必需要傳入response的對象以及返回response的對象spa
4.1 咱們在flask導入request,這個request是一個全局的變量,咱們怎麼經過request區分我當前的request對象(environ) 咱們發現request是LocalProxy的對象 4.2 當咱們用全局的request.屬性的時候,就會去找LocalProxy的對象,可是咱們發現裏面根本就沒有 那他必定執行LocalProxy對象的__getattr__方法 4.3 咱們如今來看LocalProxy對象的__getattr__方法的源碼: #name咱們要獲取屬性名 def __getattr__(self, name): if name == "__members__": return dir(self._get_current_object()) #form #self._get_current_object()就是ctx裏面的request, return getattr(self._get_current_object(), name) 4.3.1 經過反射self._get_current_object()對象,來找咱們屬性,也就是name self._get_current_object()的源碼: def _get_current_object(self): if not hasattr(self.__local, "__release_local__"): return self.__local() try: #self.__local就實例化傳過來的偏函數, return getattr(self.__local, self.__name__) except AttributeError: raise RuntimeError("no object bound to %s" % self.__name__) 4.3.1.1 return getattr(self.__local, self.__name__)那這裏self.__local是誰? def __init__(self, local, name=None): object.__setattr__(self, "_LocalProxy__local", local) self.___local爲local 這個local爲實例化的時候傳的 4.3.1.1.1 這個實例化的時候的操做 request = LocalProxy(partial(_lookup_req_object, "request")) 4.3.1.1的local就是 partial(_lookup_req_object, "request")的地址 4.3.1.1.2 _lookup_req_object的源碼: #調用的時候 partial(_lookup_req_object, "request") #如今的name就是"request" def _lookup_req_object(name): # top是當前線程的ctx top = _request_ctx_stack.top if top is None: raise RuntimeError(_request_ctx_err_msg) #找top裏面的request # ctx找request return getattr(top, name) 4.3.1.1.2 咱們來看這個_request_ctx_stack.top的top方法 def top(self): try: return self._local.stack[-1] except (AttributeError, IndexError): return None 咱們發現這個self._local是Local()對象,這樣就把ctx拿到了