std''OrgnlDave
std''OrgnlDave

Reputation: 3968

Python - easy way to treat exception catching as a generic function

Let's say I have the following code, plus 10 more.

try:
   session.get('http://www.google.com')
except rex.MissingSchema as e:
    raise RESTClientException('Bad URL for request: ' + str(url), 'error:url', e)
except rex.ConnectionError as e:
    raise RESTClientException('Cannot connect for token', 'error:connection', e)
except rfcex.InsecureTransportError as e:
    raise RESTClientException('Verify certificates True without https', 'error:https', e)

Let's say I want to use all these same except's, exactly how they are, in multiple functions. The only way I can think to do this is:

try:
    session.get('http://www.google.com')
except Exception as e:
    interpret_exception(e)

def interpret_exception(e)
    if isinstance(e, rex.MissingSchema):
        raise RESTClientException('Bad URL for request: ' + str(url), 'error:url', e)
    elif isinstance(e, rex.ConnectionError):
        raise RESTClientException('Cannot connect for token', 'error:connection', e)
    #etc...

Is there a better way to do this? Thanks

Upvotes: 1

Views: 159

Answers (1)

timmwagener
timmwagener

Reputation: 2526

I use a decorator for the purpose of wrapping certain types of known exceptions that might occur in a function into another exception type. The goal is to provide client code with a single exception type to except against. This might help you with re-raising a RESTClientException for each function elegantly, if that's what you are mainly after. However it will not convert any error messages. (Maybe that was more important for you, as the original messages aren't clear enough!?)

def wrap_known_exceptions(exceptions_to_wrap, exception_to_raise):
"""Wrap a tuple of known exceptions into another exception to offer client
code a single error to try/except against.

Args:
    exceptions_to_wrap (instance or tuple): Tuple of exception types that
        are caught when arising and wrapped.
    exception_to_raise (Exception type): Exception that will be raised on
        an occurence of an exception from ``exceptions_to_wrap``.

Raises:
    exception_to_raise's type.
"""
def closure(func):

    @wraps(func)
    def wrapped_func(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except exceptions_to_wrap as exception_instance:
            msg = u"wraps {0}: {1}"
            msg = msg.format(type(exception_instance).__name__, exception_instance)
            raise exception_to_raise(msg)

    return wrapped_func
return closure

Here's how it's used:

class RESTClientException(Exception):
    """RESTClientException"""

@wrap_known_exceptions(ValueError, RESTClientException)  # could also be a tuple
def test():
    raise ValueError("Problem occured")

test()

Outputs:

Traceback (most recent call last):
  File "C:/symlinks/..../utilities/decorators.py", line 69, in <module>
    test()
  File "C:/symlinks/..../utilities/decorators.py", line 32, in wrapped_func
    raise exception_to_raise(msg)
__main__.RESTClientException: wraps ValueError: Problem occured

Upvotes: 1

Related Questions