Search code examples
pythonpython-3.xexceptionflaskraise

python2 vs. python3 raise statement


In the flask documentation there is an example for a hook function that allows to add custom behaviour for the url_for function by being called, when no flask-defined url endpoint is found. The programmer can add a custom endpoint or re-raise the exception (with the original context) if there is no matching user defined url endpoint as well.

def external_url_handler(error, endpoint, values):
    "Looks up an external URL when `url_for` cannot build a URL."
    # This is an example of hooking the build_error_handler.
    # Here, lookup_url is some utility function you've built
    # which looks up the endpoint in some external URL registry.
    url = lookup_url(endpoint, **values)
    if url is None:
        # External lookup did not have a URL.
        # Re-raise the BuildError, in context of original traceback.
        exc_type, exc_value, tb = sys.exc_info()
        if exc_value is error:
            raise exc_type, exc_value, tb
        else:
            raise error
    # url_for will use this result, instead of raising BuildError.
    return url

app.url_build_error_handlers.append(external_url_handler)

This code snippet seems to be python2 code and fails for python3 because of the raise exc_type, exc_value, tb line. The python2 and python3 documentation list different arguments for the raise statement.

What is the correct way to convert this snippet to python3?


Solution

  • This is specified in the documentation for the raise statement:

    You can create an exception and set your own traceback in one step using the with_traceback() exception method (which returns the same exception instance, with its traceback set to its argument), like so:

    raise Exception("foo occurred").with_traceback(tracebackobj)
    

    So, in your case, that would be:

    raise exc_type(exc_value).with_traceback(tb)