Using exceptions as context managers

Some colleagues of mine came up with the idea to add methods to exceptions that would act as a context manager and a decorator to catch some exceptions and turn them to other specific types of exceptions, and to catch all other exceptions and turn them into a general IDKException. The idea is to use this in our layered architecture to have each layer only produce errors of that it declares. Like so:

class MyLayerError(Exception):
    @contextmanager
    def reraise(fn):
        try:
            yield
        except Exception as e:
            raise MyLayerError() from e


    def wrap():
        def wrapped(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            except ConcreteError as e:
                raise MyLayerError() from e
            except OtherError as e:
                # do some recovery
                raise MyLayerError() from e


@MyLayerError.wrap
def some_fn():
    with MyOtherSimilarError.reraise():
        return 3 / 0

I am not a huge fan of this idea and see a number of issues here. But could I be wrong? What does the community here think about it?

I think this is a domain-error in that the behavior of the class is not that of an exception.

The other thought I have is that this is going to create a maintenance burden on people that read the code later, especially after the author is not around to explain the mechanism.

I’ll be interested in what other think.

2 Likes