1.启动先执行manage.py 中的 app.run()
def run(self, host=None, port=None, debug=None, **options): from werkzeug.serving import run_simple try: #run_simple 是werkzeug 提供的方法,会执行第三个参数 self() run_simple(host, port, self, **options)
执行app(),对象()表示调用对象的__call__方法
def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response)
又调用了app.wsgi_app方法
def wsgi_app(self, environ, start_response): #1.
ctx = self.request_context(environ)
#self.request_context #2. ctx.push()
try: try:
#3. response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: 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步:执行app.request_context方法,把请求的相关信息传进去了
def request_context(self, environ): return RequestContext(self, environ)
返回了一个RequestContext类的实例对象
def __init__(self, app, environ, request=None): self.app = app if request is None: request = app.request_class(environ)
#app.request_class = Request self.request = request self.session = None
在init构造方法中注意app又调用了request_class方法,也就是Request 实例一个对象,
那么到这为止我们知道:
ctx是一个RequestContext对象,这个对象里面封装了两个主要的属性,一个是self.request = Request实例的对象,Request对象里面封装了请求进来的所有数据;
另外一个是self.session = None就可以了
第2步:执行ctx.push()方法
因为ctx是RequestContext类的对象,那我们就要去RequestContext类中找push方法
def push(self): #1. app_ctx = _app_ctx_stack.top if app_ctx is None or app_ctx.app != self.app: app_ctx = self.app.app_context()
# self.app.app_context = app.app_context = AppContext(app) app_ctx.push()
#2.
_request_ctx_stack.push(self)
#_request_ctx_stack = LocalStack()
#3.
self.session = self.app.open_session(self.request)
#判断没有 secret_key时:
if self.session is None:
self.session = self.app.make_null_session()
#raise RuntimeError(‘The session is unavailable because no secret ‘‘key was set.)
第1步:到_app_ctx_stack这个栈中取最后一个数据,如果未取到或者取到的app不是当前的app,就调用app.app_context()方法,就是新实例一个app对象,再执行app.push()方法 (在这再次强调,因为app是AppContext对象,就要先去AppContext类中找push方法),
def push(self): _app_ctx_stack.push(self) #把新创建的app对象添加到了_app_ctx_stack这个栈中 appcontext_pushed.send(self.app) #在这里遇到了第一个信号,请求app上下文push时执行
第2步:LocalStack类的对象调用push方法
def push(self, obj): rv = getattr(self._local, ‘stack‘, None) #self._local = Local()
#第一次的时候rv肯定是None if rv is None: self._local.stack = rv = [] #Local对象 .stack = rv = [] 就执行了对象的 __setattr__方法 rv.append(obj) return rv
try: from greenlet import getcurrent as get_ident except ImportError: try: from thread import get_ident except ImportError: from _thread import get_ident class Local(object):
def __init__(self):
object.__setattr__(self, ‘__storage__‘, {}) #这里为什么用object.__setattr__ 而不是直接用self.__storage__={}
object.__setattr__(self, ‘__ident_func__‘, get_ident) #如果用self的方式设置属性,就会触发self的__setattr__方法,就会无限的循环
def __setattr__(self, name, value): ident = self.__ident_func__() storage = self.__storage__ try: storage[ident][name] = value except KeyError: storage[ident] = {name: value}