Flask framework source code reading the entire process
""" app.run() The nature of execution is run_simple (ip, host, self) self is the current target app app.__call__ """
_request_ctx_stack = LocalStack() _app_ctx_stack = LocalStack() current_app = LocalProxy(_find_app) request = LocalProxy(partial(_lookup_req_object, "request")) session = LocalProxy(partial(_lookup_req_object, "session"))
DEF wsgi_app (Self, Environ, The start_response): # the RequestContext object, something which contains the current request. = CTX self.request_context (Environ) error = None the try : the try : # RequestContext object, ctx.push, the push method is executed RequestContext object # CTX placed in local ctx.push () # request and the response function expansion Response = self.full_dispatch_request () the except Exception as e: error = and response = self.handle_exception(e) except: # noqa: B001 error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error)
# 1 We self.request_context (environ) execution is: So ctx is RequestContext (self, environ) return value: DEF request_context (Self, Environ): # wait to return ctx is the result of RequestContext () execution. return RequestContext (Self, Environ) # 2 RequestContext (Self, Environ) What are the results of the implementation? RequestContext is the object that contains other information in the reuqest class RequestContext (Object): # App, Environ, ctx, is RequestContext object DEF __init__ (Self, App, Environ, Request = None, the session = None): self.app = app if request is None: request = app.request_class(environ) self.request = request
# The Push method 1 ctx.push method of implementation of the object RequestContext: # Source: DEF the Push (self): # The current self is RequestContext object is ctx, _request_ctx_stack.push (self) # 2 _request_ctx_stack, we found it It is a global LocalStack () object. # _Request_ctx_stack.push (Self) is the implementation of the method LocalStack push in and push the ctx passed to the method # _request_ctx_stack.push. ctx = Self # LocalStack the push Source: def push(self, obj): rv = getattr(self._local, "stack", None) if rv is None: #storage[线程,协程id]["stack"] = [] self._local.stack = rv = [] rv.append(obj) return rv # Above code self._local Local objects are used to ensure data security. # When the code execution self._local.stack = rv = [], and then Local storage structure object is: storage [thread coroutine ID] [ "Stack"] = [] # rv.append (obj), the storage [thread coroutine id] [ "stack"] = [obj], and because obj = ctx, even is placed into the ctx Local object. Structure as Local (). Storage [threads coroutine id] [ "stack"] = [ctx]
# 1 # This sentence is to ask us to perform expansion and response function # and then extension request and response functions you can use request, and if it is to achieve it? from the Flask Import the Flask, Request, the session App = the Flask ( __name__ ) DEF index (): Print (request.method) Print (the session) return " the ok " # example code above request.method, is how to get the request related to the content? #2 # We get to see what and request is the point? = LocalProxy request (partial (_lookup_req_object, " request " )) # We found that the object of the request is LocalProxy. # Then we should be able to find another method LocalProxy property, but found no, since there is no, it must write a __getattr__ # we look __getattr__ source: DEF __getattr__ (Self, name): # request.method, now name is Method, IF name == " __members__ " : return dir (self._get_current_object ()) # now the name is the method, the results self._get_current_object () function execution result on the side of # the results of the partial function to obtain Method, # the results of partial functions that request. #etattr(request, method) return getattr(self._get_current_object(), name) # 3 # we look at _get_current_object () What is its execution result? # Self._get_current_object () source: DEF _get_current_object (Self): return Self. __Local () # () execution result is self .__ local () to perform the above results self._get_current_object # 4 # Self .__ local is what? # We have found this is an instance of self .__ local time passed, also local, the following code DEF __init__ (Self, local, name = None): # self .__ local _LocalProxy__local = = = partial local (_lookup_req_object, "Request") # Self .__ local property set to hide, Object. __setattr__ (Self, " _LocalProxy__local " , local) # Self .__ local = local # Local is instantiated delivery. We instantiate this LocalProxy (partial (_lookup_req_object, "Request")) # We self._get_current_object = self .__ local = local = partial (_lookup_req_object, "request") # 5 # that ultimately we understand: DEF __getattr__ (Self, name): # request.method, the name is now Method, IF name == " __members__ " : return dir (self._get_current_object ()) return getattr (self._get_current_object (), name) # Self._get_current_object () the results of the implementation of the results of partial (_lookup_req_object, "request") is. # Is ctx.request, so getattr (self._get_current_object (), name) is equivalent to getattr (ctx.request, method) # . 6 # partial (_lookup_req_object, "Request") () result of execution # _lookup_req_object code is as follows: DEF _lookup_req_object (name): # name here is "Request" Top = _request_ctx_stack.top # Who top that? Is ctx. IF Top IS None: The raise RuntimeError (_request_ctx_err_msg) # Top inside to find request, namely top = ctx - "ctx find inside Request. Return getattr (Top, name) # 7 # objects and because _request_ctx_stack is LocalStack () object, so _request_ctx_stack.top is executed LocalStack () in the Top: # _request_ctx_stack.top source: the @Property DEF Top (Self): the try : # Storage [ thread, coroutine ID] [ "Stack"] = [CTX] # now on top retrun value CTX return self._local.stack [-1 ] the except (AttributeError, IndexError): return None # code is self._local Local objects, the object is Local time of our existence ctx.