How to use original_exception of InternalServerError

Viewed 105

according to werkzeug docs, InternalServerError has original_exception parameter. That looks cool and I'would like to use it in following way to handle exceptions:

@app.errorhandler(Exception)
def handle_errors(err):
    return err if isinstance(err, HTTPException) else InternalServerError(original_exception=err)

and log it in @app.after_request method to pack all additional info from request and response, where standard request logging occurs. Unfortunatelly I'm not able to find out how to use stored original_exception. Where is it stored?

When I check sys.exc_info() in @app.after_request, it's also empty (or (None, None, None)).

One way is probably log exceptions directly in @app.errorhandler, request info should be accessible there and response is not ready (because of error) anyways, but what happens with original_exception after storing in InternalServerError???

Thanks for answer, Michal

1 Answers

I found myself here looking for the same thing - how to access the original_exception, but I eventually gave up and settled on traceback to give me the info I was seeking.

This is the key component, capturing the traceback stack as a list:

formatted_lines = traceback.format_exc().splitlines()

Here's my final code in which I extracted the line number of the error and the specific trigger, then passed them to the page:

from werkzeug.exceptions import InternalServerError
import traceback

@app.errorhandler(InternalServerError)
def handle_500(e):
    templateData = {
        'errorAt' : 'Internal Server Error',
        'errorIs' : 'Check ~/www/gunicorn.error for details'
    }
    try:
        formatted_lines = traceback.format_exc().splitlines()
        for error_location in formatted_lines:
            if 'intvlm8r.py' in error_location:
                templateData['errorAt'] = error_location
        templateData['errorIs'] = formatted_lines[-1]
    except Exception as e:
        app.logger.debug(f'handle_500: Unhandled exception: {e}')
    return render_template('500_generic.html', **templateData)
Related