사용자의 07 플라스크 소스 코드 분석 프로세스를 통해 요청

사용자 요청이 올 과정 : 07 플라스크 소스

객체를 만들기 1. CTX = RequestContext

  • 패키지 개체 Request 객체의 RequestContext

  • RequestContext 세션 객체 데이터를 캡슐화

  • 소스를 달성 :

    def wsgi_app(self, environ, start_response):
        """
            ctx = RequestContext(self, environ)
            """
        # 2.1 创建RequestContext对象
        ctx = self.request_context(environ)
    def request_context(self, environ):
        return RequestContext(self, environ)
    request_class = Request
    
    class RequestContext(object):
        def __init__(self, app, environ, request=None, session=None):
            self.app = app
            if request is None:
                """
                request_class = Request
                """
                request = app.request_class(environ)
            self.request = request
            self.session = session

app_ctx = AppContext 개체 만들기 (2)

  • 응용 프로그램 개체 개체는 AppContext를 캡슐화

  • AppContext 객체 캡슐화 g

  • 소스를 달성 :

    def wsgi_app(self, environ, start_response):
        """
            ctx = RequestContext(self, environ)
            """
        # 2.1 创建RequestContext对象
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                """
                2.2 执行ctx.push
                    - app_ctx = 创建AppContext对象(app,g)
                    - 将app_ctx放入local中
                    - 将ctx放入到local中
                    - session赋值
                    - 路由匹配
                 """
                ctx.push()
        def push(self):
            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 = AppContext(app)
                """
                # 创建appcontext对象
                app_ctx = self.app.app_context()
    def app_context(self):
        return AppContext(self)
    class AppContext(object):
        def __init__(self, app):
            self.app = app
            self.g = app.app_ctx_globals_class()

3. CTX 객체, 로컬에 app_ctx 객체

  • Ctx.push는 트리거 CTX 객체는 자신의 LocalStack을 통해 현지에 배치하는 것

  • 그런 다음 app_ctx.push 트리거는 지역에 배치하기 위해 자신의 LocalStack을 통해 객체를 app_ctx합니다

  • 키 같은 스레드 ID의 특성에 기초하여, 국부적 { "스택"[]} 사전 값인

    저장 구조 {
    1,111 : { "스택"[CTX,]}
    };

    {
    1111 : { "스택"[app_ctx,]}
    }

  • 소스 코드 예제 :

        def push(self):
            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 = AppContext(app)
                """
                # 创建appcontext对象
                app_ctx = self.app.app_context()
                # push将app_ctx放入到local中
                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()
            """
            self = ctx = RequestContext(self, environ)
            """
            # push将ctx放入到local中
            _request_ctx_stack.push(self)
    
            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:
                # 路由匹配,将匹配到的endpoint放到request.url_rule中
                self.match_request()

4. 모든 기능을 수행하는 모든 기능 before_request보기

  1. Full_dispatch_request 기능 수행
  2. before_request의 모든 기능을 수행합니다
  3. 보기 기능을 실행
  • 소스 코드 예제 :

    def wsgi_app(self, environ, start_response):
        """
            ctx = RequestContext(self, environ)
        """
        #2.1 创建RequestContext对象
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                # 做了很多事
                """
                    2.2 执行ctx.push
                        - app_ctx = 创建AppContext对象(app,g)
                        - 将app_ctx放入local中
                        - 将ctx放入到local中
                        - session赋值
                        - 路由匹配
                 """
                ctx.push()
                # 2.3 执行before_request/视图/after_request (处理session)
                response = self.full_dispatch_request()
    def full_dispatch_request(self):
        # 触发所有的before_first_request_funcs函数
        # 只在启动程序后,第一个请求到来时执行
        self.try_trigger_before_first_request_functions()
        try:
            # 信号,暂留
            request_started.send(self)
            # 执行before_request_funcs函数,如果有返回值就不执行视图函数了
            rv = self.preprocess_request()
            if rv is None:
                # 执行视图函数
                rv = self.dispatch_request()
                except Exception as e:
                    rv = self.handle_user_exception(e)
                    # 视图函数执行之后
                    #  1.执行所有的after_request
                    #  2.保存session
                    return self.finalize_request(rv)

모든 기능의 구현 after_request

  • 세션 암호화는 쿠키에 사용자의 브라우저에 반환됩니다

  • 소스 코드 예제 :

    def finalize_request(self, rv, from_error_handler=False):
        # 将rv视图函数返回值,封装到Reponse对象中
        response = self.make_response(rv)
        response = self.process_response(response)
        return response
    response_class = Response
    
    def make_response(self, rv):
        if not isinstance(rv, self.response_class):
            if isinstance(rv, (text_type, bytes, bytearray)):
                rv = self.response_class(rv, status=status, headers=headers)
                return rv
    def process_response(self, response):
        ctx = _request_ctx_stack.top
        funcs = ctx._after_request_functions
        # 执行所有的after_request_funcs
        funcs = chain(funcs, reversed(self.after_request_funcs[None]))
        for handler in funcs:
            response = handler(response)
            if not self.session_interface.is_null_session(ctx.session):
                # 保存session
                self.session_interface.save_session(self, ctx.session, response)
                return response

6. CTX 파괴와 app_ctx

  • 요청이 파괴와 app_ctx CTX의 끝이 아닌 경우, 메모리 누수 될 것입니다

  • 통화 CTX 팝 방법의 app_ctx

  • 소스 코드 예제 :

    def wsgi_app(self, environ, start_response):
        """
            ctx = RequestContext(self, environ)
        """
        #2.1 创建RequestContext对象
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                """
                    2.2 执行ctx.push
                        - app_ctx = 创建AppContext对象(app,g)
                        - 将app_ctx放入local中
                        - 将ctx放入到local中
                        - session赋值
                        - 路由匹配
                 """
                ctx.push()
                # 2.3 执行before_request/视图/after_request (处理session)
                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
                        return response(environ, start_response)
                    finally:
                        if self.should_ignore_error(error):
                            error = None
                            # 2.4 销毁ctx/app_ctx
                            ctx.auto_pop(error)
    
    def auto_pop(self, exc):
        self.pop(exc)
    def pop(self, exc=_sentinel):
        app_ctx = self._implicit_app_ctx_stack.pop()
        finally:
            rv = _request_ctx_stack.pop()
            if app_ctx is not None:
                app_ctx.pop(exc)

추천

출처www.cnblogs.com/liubing8/p/11930727.html