All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.l10n.py.rules.python.S1045.html Maven / Gradle / Ivy

There is a newer version: 4.23.0.17664
Show newest version

This rule raises an issue when an except statement has had all its exceptions caught by a previous except clause.

Why is this an issue?

Exceptions handlers (except) are evaluated in the order they are written. Once a match is found, the evaluation stops.

In some contexts, an except block is dead code as it will never catch any exception:

  • If there is a handler for a base class followed by a handler for class derived from that base class, the second handler will never trigger: The handler for the base class will match the derived class, and will be the only executed handler.
  • When multiple except statements try to catch the same exception class, only the first one will be executed.
  • In Python 3, BaseException is the parent of every exception class. When a BaseException is caught by an except clause, none of the subsequent except statement will catch anything. This is true as well for the bare except statement (except:).

How to fix it

When using multiple except statements, make sure to:

  • Order the except blocks from the most specialzed exception to the most generic, i.e when wanting to catch a FloatingPointError and an ArithemticError, as FloatingPointError is a subclass of ArithmeticError, the first except statement should be FloatingPointError.
  • Catch the same exception only once.
  • Catch a BaseException only once with either an except BaseException: statement or a bare except: statement, as the two statements are equivalent.

Code examples

Noncompliant code example

def foo():
    try:
        raise FloatingPointError()
    except (ArithmeticError, RuntimeError) as e:
        print(e)
    except FloatingPointError as e: # Noncompliant: FloatingPointError is a subclass of ArithmeticError.
        print("Never executed")
    except OverflowError as e: # Noncompliant: OverflowError is a subclass of ArithmeticError.
        print("Never executed")

    try:
        raise TypeError()
    except TypeError as e:
        print(e)
    except TypeError as e: # Noncompliant: duplicate except.
        print("Never executed")

    try:
        raise ValueError()
    except BaseException as e:
        print(e)
    except: # Noncompliant: this is equivalent to "except BaseException" block.
        print("Never executed")

Compliant solution

def foo():
    try:
        raise FloatingPointError()
    except FloatingPointError as e:
        print("Executed")
    except OverflowError as e:
        print("Executed")
    except (ArithmeticError, RuntimeError) as e:
        print(e)

    try:
        raise TypeError()
    except TypeError as e:
        print(e)

    try:
        raise ValueError()
    except BaseException as e:
        print(e)

Note: It is generally not recommended to try catching BaseException, as it is the base class for all built-in exceptions in Python, including system-exiting exceptions like SystemExit or KeyboardInterrupt, which are typically not meant to be caught. See PEP 352 for more information.

Resources

Documentation





© 2015 - 2024 Weber Informatics LLC | Privacy Policy