Except 块处理“BaseException”¶
ID: py/catch-base-exception
Kind: problem
Security severity:
Severity: recommendation
Precision: very-high
Tags:
- reliability
- readability
- convention
- external/cwe/cwe-396
Query suites:
- python-security-and-quality.qls
Python 中所有异常类都派生自 BaseException。 BaseException 有三个重要的子类,Exception,所有错误和普通异常都派生自它,KeyboardInterrupt,当用户从键盘中断程序时引发它,以及 SystemExit,它由 sys.exit() 函数引发以终止程序。
由于 KeyboardInterrupt 和 SystemExit 是特殊的,因此不应该将它们与其他 Exception 类分组在一起。
捕获 BaseException 而不是它的子类可能会阻止正确处理 KeyboardInterrupt 或 SystemExit。由于空 except: 语句会隐式捕获它,因此很容易意外地捕获 BaseException。
建议¶
分别处理 Exception、KeyboardInterrupt 和 SystemExit。不要使用简单的 except: 形式。
示例¶
在这些示例中,调用了一个可能引发 SystemExit 的函数 application.main()。在前两个函数中,捕获了 BaseException,但这会丢弃 KeyboardInterrupt。在第三个函数 call_main_program_fixed 中,只捕获了 SystemExit,使 KeyboardInterrupt 传播。
在这些示例中, KeyboardInterrupt 被意外忽略。
def call_main_program_implicit_handle_base_exception():
try:
#application.main calls sys.exit() when done.
application.main()
except Exception as ex:
log(ex)
except:
pass
def call_main_program_explicit_handle_base_exception():
try:
#application.main calls sys.exit() when done.
application.main()
except Exception as ex:
log(ex)
except BaseException:
pass
def call_main_program_fixed():
try:
#application.main calls sys.exit() when done.
application.main()
except Exception as ex:
log(ex)
except SystemExit:
pass