Home > Back-end >  Registered error handler in Python/Flask application does not work
Registered error handler in Python/Flask application does not work

Time:12-12

I create a Python/Flask application with the following code in main.py:

import json

from flask import Flask, jsonify
from werkzeug.exceptions import HTTPException, default_exceptions

from blueprints import test

def create_app(config_filename=None) -> Flask:
   """Application factory function
   """
   app = Flask(__name__, instance_relative_config=True)
   if config_filename:
       app.config.from_pyfile(config_filename)

   for exc in default_exceptions:
       app.register_error_handler(exc, handle_error)        

   register_blueprints(app)
   return app

def handle_error(error):
   code = 500
   if isinstance(error, HTTPException):
       code = error.code
   return jsonify(error='error', code=code)    


def register_blueprints(app: Flask):
   """Register blueprints
   """
   app.register_blueprint(test.bp)


def handle_exception(ex: HTTPException):
   """Return JSON instead of HTML for HTTP errors."""
   # start with the correct headers and status code from the error
   response = ex.get_response()
   # replace the body with JSON
   response.data = json.dumps({
       "code": ex.code,
       "error": ex.name,
       "message": ex.description,
   })
   response.content_type = "application/json"
   return response


if __name__ == '__main__':
   main_app = create_app()
   main_app.run(host='0.0.0.0', port=80, debug=True, threaded=False)

and the source code of the test.py blueprint is:

from flask import Blueprint, jsonify, request
from werkzeug.exceptions import HTTPException, default_exceptions

bp = Blueprint('blabla', __name__)

@bp.route('/blabla', methods=['POST'])
def blabla():
   """Test blueprint
   """
   raise MyException()

class MyException(HTTPException):

   code = 409
   name = 'My Exception'
   description = 'My Exception'

unfortunately when i execute the endpoint, the exception is not handled by the method, defined in the main.py

I even decided and tried to register error handlers in the blueprint, but the result is the same - the exception is not handled by the methods.

Here is the modified test.py

from flask import Blueprint, jsonify, request
from werkzeug.exceptions import HTTPException, default_exceptions

bp = Blueprint('blabla', __name__)

@bp.errorhandler(409)
def error_handler(e):
    return handle_error(e)

@bp.route('/blabla', methods=['POST'])
def blabla():
    """Test blueprint
    """
    raise MyException()

def handle_error(error):
    code = 500
    if isinstance(error, HTTPException):
        code = error.code
    return jsonify(error='error', code=code)

class MyException(HTTPException):

    code = 409
    name = 'My Exception'
    description = 'My Exception'

Can someone tell me what is my error? Why the exception is not handled by the error methods?

CodePudding user response:

This example is directly from flask, which has slight differences in terms of your code, for example, in @app.errorhandler(404) decorator they check request users as follows request.path.startswith(''), maybe this is not the source of your error but I recommend that you carefully read the examples and instructions to handle errors using blue print error handlers.

from flask import jsonify, render_template

# at the application level
# not the blueprint level
@app.errorhandler(404)
def page_not_found(e):
    # if a request is in our blog URL space
    if request.path.startswith('/blog/'):
        # we return a custom blog 404 page
        return render_template("blog/404.html"), 404
    else:
        # otherwise we return our generic site-wide 404 page
        return render_template("404.html"), 404

@app.errorhandler(405)
def method_not_allowed(e):
    # if a request has the wrong method to our API
    if request.path.startswith('/api/'):
        # we return a json saying so
        return jsonify(message="Method Not Allowed"), 405
    else:
        # otherwise we return a generic site-wide 405 page
        return render_template("405.html"), 405

CodePudding user response:

Actually it came out, that the error handler has to be registered after the blueprints:

def register_blueprints(app: Flask):
    app.register_blueprint(test.bp)
    
    app.register_error_handler(HTTPException, handle_exception)

def handle_exception(ex: HTTPException):
    """Return JSON instead of HTML for HTTP errors."""
    # start with the correct headers and status code from the error
    response = ex.get_response()
    # replace the body with JSON
    response.data = json.dumps({
        "code": ex.code,
        "error": ex.name,
        "message": ex.description,
    })
    response.content_type = "application/json"
    return response
  • Related