美文网首页
Flask中的error_handler

Flask中的error_handler

作者: 黄智勇atTAFinder | 来源:发表于2016-09-04 16:31 被阅读0次
    from flask import Flask 
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return 'Saltriver'
    
    @app.errorhandler(404)        # <---
    def page_not_found(error):
        return '---Not Found---', 404
        
    if __name__ == '__main__':
        app.run()
    
        @setupmethod
        def errorhandler(self, code_or_exception):
            # code_or_exception为404或者其他.
            def decorator(f):
                # 注册.
                self._register_error_handler(None, code_or_exception, f)
                return f
            return decorator
    
        @setupmethod
        def _register_error_handler(self, key, code_or_exception, f):
            """
            :type key: None|str
            :type code_or_exception: int|T<=Exception
            :type f: callable
            """
            if isinstance(code_or_exception, HTTPException):  # old broken behavior
                raise ValueError(
                    'Tried to register a handler for an exception instance {0!r}. '
                    'Handlers can only be registered for exception classes or HTTP error codes.'
                    .format(code_or_exception))
    
            exc_class, code = self._get_exc_class_and_code(code_or_exception)
    
            handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {})
            handlers[exc_class] = f
    
        # app.py
        def _get_exc_class_and_code(exc_class_or_code):
          
            if isinstance(exc_class_or_code, integer_types):
                # 如果exc_class_or_code是integer_types,比如示例中传入的参数404
                exc_class = default_exceptions[exc_class_or_code]
            else:
                # 如果exc_class_or_code是,比如, werkzeug.exceptions.BadRequest
                exc_class = exc_class_or_code
            
            # 其他类型参数就不得行
            assert issubclass(exc_class, Exception)
    
            if issubclass(exc_class, HTTPException):
                # 如果是继承自HTTPException的类,那么返回示例和响应的code.
                return exc_class, exc_class.code
            else:
                # 否则code就设置为None,自定义???
                return exc_class, None
    

    执行完毕之后, error_handler_spec就有了注册的相应的错误处理程序了.对于示例程序而言,注册完后, Flask.error_handler_spec就变成如下了:

    None {
      400: {<class 'werkzeug.exceptions.BadRequest'>: 
                      <function handle_bad_request at 0x102cb7510>}, 
      404: {<class 'werkzeug.exceptions.NotFound'>: 
                      <function page_not_found at 0x102cad2f0>},
      None: {<class '__main__.myException'>: 
                      <function handle_Blablabla_Error at 0x102cb7598>}
    }
    

    Part2


        def wsgi_app(self, environ, start_response): 
            ctx = self.request_context(environ)
            ctx.push()
            error = None
            try:
                # ------------------------------------------------
                try:
                    response = self.full_dispatch_request()
                except Exception as e:
                    error = e
                    response = self.make_response(self.handle_exception(e))
                # ------------------------------------------------
                return response(environ, start_response)
            finally:
                if self.should_ignore_error(error):
                    error = None
                ctx.auto_pop(error)
    

    下面我们重点看full_dispatch_request(...)

        def full_dispatch_request(self):
            self.try_trigger_before_first_request_functions()
            try:
                request_started.send(self)     # signal.
                rv = self.preprocess_request()    # <---
                if rv is None:
                    rv = self.dispatch_request()    # <---
            except Exception as e:
                rv = self.handle_user_exception(e)
            response = self.make_response(rv)
            response = self.process_response(response)
            request_finished.send(self, response=response)
            return response
    

    在full_dispatch_request()中,我们又重点看dispatch_request().

        def dispatch_request(self):
            req = _request_ctx_stack.top.request
            if req.routing_exception is not None:
                self.raise_routing_exception(req)
            ...
    
        # ctx.py
        def match_request(self):
            try:
                url_rule, self.request.view_args = \
                    # 如果无法匹配时,就抛出HTTPException.
                    self.url_adapter.match(return_rule=True)
                self.request.url_rule = url_rule
            # 捕获并将self.request.routing_exception设置为e.
            except HTTPException as e:
                self.request.routing_exception = e
    
        def raise_routing_exception(self, request):
            ...
            if not self.debug \
               or not isinstance(request.routing_exception, RequestRedirect) \
               or request.method in ('GET', 'HEAD', 'OPTIONS'):
                # 抛出异常.
                raise request.routing_exception   # <---
            ...
    

    相关文章

      网友评论

          本文标题:Flask中的error_handler

          本文链接:https://www.haomeiwen.com/subject/qogkettx.html