
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
108 lines
3.2 KiB
Plaintext
108 lines
3.2 KiB
Plaintext
== Why is this an issue?
|
||
|
||
https://docs.python.org/3/library/exceptions.html#SystemExit[``++SystemExit++``] is raised when https://docs.python.org/3/library/sys.html#sys.exit[``++sys.exit()++``] is called. This exception is expected to propagate up until the application stops. It is ok to catch it when a clean-up is necessary but it should be raised again immediately.
|
||
|
||
|
||
A https://docs.python.org/3/reference/compound_stmts.html#the-try-statement[bare ``++except:++`` statement], i.e. an ``++except++`` without any exception class, is equivalent to https://docs.python.org/3/library/exceptions.html#BaseException[``++except BaseException++``]. Both statements will catch every exception, including ``++SystemExit++``. It is recommended to catch instead a specific exception. If it is not possible, the exception should be raised again.
|
||
|
||
|
||
Note that it is also a good idea to reraise the https://docs.python.org/3/library/exceptions.html#KeyboardInterrupt[``++KeyboardInterrupt++``] exception.
|
||
|
||
|
||
This rule raises an issue when a bare ``++except:++``, an ``++except BaseException++`` or an ``++except SystemExit++`` don't reraise the exception caught.
|
||
|
||
|
||
=== Noncompliant code example
|
||
|
||
[source,python]
|
||
----
|
||
try:
|
||
open("foo.txt", "r")
|
||
except SystemExit: # Noncompliant
|
||
pass
|
||
except KeyboardInterrupt: # No issue raised but be careful when you do this
|
||
pass
|
||
|
||
try:
|
||
open("bar.txt", "r")
|
||
except BaseException: # Noncompliant
|
||
pass
|
||
except: # Noncompliant
|
||
pass
|
||
----
|
||
|
||
|
||
=== Compliant solution
|
||
|
||
[source,python]
|
||
----
|
||
try:
|
||
open("foo.txt", "r")
|
||
except SystemExit:
|
||
# clean-up
|
||
raise
|
||
except KeyboardInterrupt:
|
||
# clean-up
|
||
raise
|
||
|
||
try:
|
||
open("bar.txt", "r")
|
||
except BaseException as e:
|
||
# clean-up
|
||
raise e
|
||
except: # Noncompliant
|
||
# clean-up
|
||
raise
|
||
|
||
# or use a more specific exception
|
||
|
||
try:
|
||
open("bar.txt", "r")
|
||
except FileNotFoundError:
|
||
# process the exception
|
||
----
|
||
|
||
|
||
== Resources
|
||
|
||
* 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]
|
||
* https://cwe.mitre.org/data/definitions/391[MITRE, 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[]
|