This rule raises an issue when a bare raise
statement is not in an except
or finally
block.
Why is this an issue?
A bare raise
statement, i.e. a raise
with no exception provided, will re-raise the last active exception in the current
scope:
def foo():
try:
...
except ValueError as e:
raise # this will re-raise "e"
If the raise
statement is not in an except
or finally
block, no exception is active and a
RuntimeError
is raised instead.
If the bare raise
statement is in a function called in an except
block, the exception caught by the except
will be re-raised. However, this behavior is not reliable as nothing prevents a developer from calling the function from a different context.
Overall, having bare raise
statements outside of except
blocks is discouraged as it is hard to understand and
maintain.
Notes
In a finally
block, an exception is still active only when it hasn’t been caught in a previous except
clause or if it has
been raised in an except
block. In both cases, it is better to let the exception propagate automatically than to re-raise it. This
pattern is covered by rule S5704.
How to fix it
To fix this issue, make sure to specify which exception needs to be raised when outside of an except
block.
Code examples
Noncompliant code example
raise # Noncompliant: no active exception
def foo():
raise # Noncompliant: no active exception
try:
raise # Noncompliant: no active exception
except ValueError:
handle_error()
def handle_error():
raise # Noncompliant: this is not reliable
Compliant solution
raise ValueError()
def foo():
raise ValueError()
try:
raise ValueError()
except ValueError:
raise
Resources
Documentation