码迷,mamicode.com
首页 > 编程语言 > 详细

python-flask-源码流程

时间:2018-01-17 20:23:39      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:open   gre   tco   启动   patch   handle   bug   value   exception   

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}

 

 

 

 

 

 

 

 

 

 

 

 

python-flask-源码流程

标签:open   gre   tco   启动   patch   handle   bug   value   exception   

原文地址:https://www.cnblogs.com/liuwei0824/p/8304097.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!