org.sonar.l10n.py.rules.python.S1045.html Maven / Gradle / Ivy
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