Raising instances of Exception and BaseException will have a negative impact on any code trying to catch these exceptions.

First, the only way to handle differently multiple Exceptions is to check their message, which is error-prone and difficult to maintain.

What's more, it becomes difficult to catch only your exception. The best practice is to catch only exceptions which require a specific handling. When you raise Exception or BaseException in a function the caller will have to add an except Exception or except BaseException and re-raise all exceptions which were unintentionally caught. This can create tricky bugs when the caller forgets to re-raise exceptions such as SystemExit and the software cannot be stopped.

It is recommended to either:

This rule raises an issue when Exception or BaseException are raised.

Noncompliant Code Example

def process1():
    raise BaseException("Wrong user input for field X")  # Noncompliant

def process2():
    raise BaseException("Wrong configuration")  # Noncompliant

def process3(param):
    if not isinstance(param, int):
        raise Exception("param should be an integer")  # Noncompliant

def caller():
    try:
         process1()
         process2()
         process3()
    except BaseException as e:
        if e.args[0] == "Wrong user input for field X":
            # process error
            pass
        elif e.args[0] == "Wrong configuration":
            # process error
            pass
        else:
            # re-raise other exceptions
            raise

Compliant Solution

class MyProjectError(Exception):
    """Exception class from which every exception in this library will derive.
         It enables other projects using this library to catch all errors coming
         from the library with a single "except" statement
    """
    pass

class BadUserInputError(MyProjectError):
    """A specific error"""
    pass

class ConfigurationError(MyProjectError):
    """A specific error"""
    pass

def process1():
    raise BadUserInputError("Wrong user input for field X")

def process2():
    raise ConfigurationError("Wrong configuration")

def process3(param):
    if not isinstance(param, int):
        raise TypeError("param should be an integer")

def caller():
    try:
         process1()
         process2()
         process3()
    except BadUserInputError as e:
        # process error
        pass
    except ConfigurationError as e:
        # process error
        pass

See

See