Nickpick
Nickpick

Reputation: 6597

Flask RestPlus: how to catch all exceptions and output the original error

I'm trying to catch all exceptions that may happen and output the stack details as message in FlaskRestPlus.

The below is an example that works if I raise custom exception such as RootException. But I didn't manage to get it to work with BaseException or anything else that might serve as a catch all. I also didn't find a way to output the stack (or original error message) into the message body.

@api.errorhandler(RootException)
def handle_root_exception(error):
    return {'message': 'Here I want the original error message'}, 500

Any suggestions how I can achieve this would be highly appreciated. THe documentation doesn't seem to be entirely clear: https://flask-restplus.readthedocs.io/en/stable/errors.html

Upvotes: 3

Views: 1712

Answers (1)

Christopher Peisert
Christopher Peisert

Reputation: 24194

To create a generic error handler, you can use:

@api.errorhandler(Exception)
def generic_exception_handler(e: Exception):

Stack Trace Capturing

To customize stack trace handling, see Python When I catch an exception, how do I get the type, file, and line number?.

Example stack trace data capture

import sys

...

@api.errorhandler(Exception)
def generic_exception_handler(e: Exception):
    exc_type, exc_value, exc_traceback = sys.exc_info()

    if exc_traceback:
        traceback_details = {
            'filename': exc_traceback.tb_frame.f_code.co_filename,
            'lineno': exc_traceback.tb_lineno,
            'name': exc_traceback.tb_frame.f_code.co_name,
            'type': get_type_or_class_name(exc_type),
            'message': str(exc_value),
        }
        return {'message': traceback_details['message']}, 500
    else:
        return {'message': 'Internal Server Error'}, 500

The function get_type_or_class_name is a helper that gets the type name of an object, or in the case of a Class, returns the Class name.

def get_type_or_class_name(var: Any) -> str:
    if type(var).__name__ == 'type':
        return var.__name__
    else:
        return type(var).__name__

It is also customary to provide an HTTPException handler:

from werkzeug.exceptions import HTTPException

@api.errorhandler(HTTPException)
def http_exception_handler(e: HTTPException):

Upvotes: 3

Related Questions