112 lines
3.7 KiB
Plaintext
112 lines
3.7 KiB
Plaintext
This rule raises an issue when a bare ``++except:++``, an ``++except BaseException++`` or an ``++except SystemExit++`` block does not re-raise the exception caught.
|
||
|
||
== Why is this an issue?
|
||
|
||
A https://docs.python.org/3/library/exceptions.html#SystemExit[``++SystemExit++``] exception is raised when https://docs.python.org/3/library/sys.html#sys.exit[``++sys.exit()++``] is called.
|
||
This exception is used to signal the interpreter to exit. The exception is expected to propagate up until the program stops.
|
||
It is possible to catch this exception in order to perform, for example, clean-up tasks. It should, however, be raised again to allow the interpreter to exit as expected.
|
||
Not re-raising such exception could lead to undesired behaviour.
|
||
|
||
|
||
A https://docs.python.org/3/reference/compound_stmts.html#the-try-statement[bare ``++except:++`` statement], i.e. an `except` block without any exception class, is equivalent to https://docs.python.org/3/library/exceptions.html#BaseException[``++except BaseException++``].
|
||
Both statements will catch every exceptions, including `SystemExit`. It is recommended to catch instead a more specific exception.
|
||
If it is not possible, the exception should be raised again.
|
||
|
||
|
||
It is also a good idea to re-raise the https://docs.python.org/3/library/exceptions.html#KeyboardInterrupt[``++KeyboardInterrupt++``] exception. Similarly to `SystemExit`,`KeyboardInterrupt` is used to signal the interpreter to exit. Not re-raising such exception could also lead to undesired behaviour.
|
||
|
||
== How to fix it
|
||
|
||
Re-raise `SystemExit`, `BaseException` and any exceptions caught in a bare `except` clause.
|
||
|
||
=== Code examples
|
||
|
||
==== Noncompliant code example
|
||
|
||
[source,python,diff-id=1,diff-type=noncompliant]
|
||
----
|
||
try:
|
||
...
|
||
except SystemExit: # Noncompliant: the SystemExit exception is not re-raised.
|
||
pass
|
||
|
||
try:
|
||
...
|
||
except BaseException: # Noncompliant: BaseExceptions encompass SystemExit exceptions and should be re-raised.
|
||
pass
|
||
|
||
try:
|
||
...
|
||
except: # Noncompliant: exceptions caught by this statement should be re-raised or a more specific exception should be caught.
|
||
pass
|
||
----
|
||
|
||
|
||
==== Compliant solution
|
||
|
||
[source,python,diff-id=1,diff-type=compliant]
|
||
----
|
||
try:
|
||
...
|
||
except SystemExit as e:
|
||
...
|
||
raise e
|
||
|
||
try:
|
||
...
|
||
except BaseException as e:
|
||
...
|
||
raise e
|
||
|
||
try:
|
||
...
|
||
except FileNotFoundError:
|
||
... # Handle a more specific exception
|
||
----
|
||
|
||
|
||
== Resources
|
||
|
||
=== Documentation
|
||
|
||
* PEP 352 - https://www.python.org/dev/peps/pep-0352/#id5[Required Superclass for Exceptions]
|
||
* Python Documentation - https://docs.python.org/3/library/exceptions.html[Built-in exceptions]
|
||
* Python Documentation - https://docs.python.org/3/reference/compound_stmts.html#the-try-statement[The ``++try++`` statement]
|
||
* CWE - https://cwe.mitre.org/data/definitions/391[CWE-391, Unchecked Error Condition]
|
||
|
||
|
||
ifdef::env-github,rspecator-view[]
|
||
|
||
'''
|
||
== Implementation Specification
|
||
(visible only on this page)
|
||
|
||
=== Message
|
||
|
||
* if it is a bare "except:":
|
||
* specify an exception class to catch or reraise the exception.
|
||
* if it catches a BaseException:
|
||
* catch a more specific exception or reraise the exception.
|
||
* if SystemExit is caught:the application as the user expects.
|
||
|
||
|
||
=== Highlighting
|
||
|
||
the "except" statement
|
||
|
||
|
||
'''
|
||
== Comments And Links
|
||
(visible only on this page)
|
||
|
||
=== relates to: S1181
|
||
|
||
=== relates to: S2142
|
||
|
||
=== relates to: S2738
|
||
|
||
=== on 6 Mar 2020, 15:05:41 Nicolas Harraudeau wrote:
|
||
This rule is similar to RSPEC-2142 but this one is a code smell because python 2 forced developers to use a bare ``++except:++`` for a long time. Thus old projects will have many issues. Yet even in python 2 it is possible to handle properly the exception. Thus we raise a code smell issue for both python 2 and python 3.
|
||
|
||
endif::env-github,rspecator-view[]
|