CodeQL 文档

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

点击查看 CodeQL 代码库中的查询

Python 中所有异常类都派生自 BaseExceptionBaseException 有三个重要的子类,Exception,所有错误和普通异常都派生自它,KeyboardInterrupt,当用户从键盘中断程序时引发它,以及 SystemExit,它由 sys.exit() 函数引发以终止程序。

由于 KeyboardInterruptSystemExit 是特殊的,因此不应该将它们与其他 Exception 类分组在一起。

捕获 BaseException 而不是它的子类可能会阻止正确处理 KeyboardInterruptSystemExit。由于空 except: 语句会隐式捕获它,因此很容易意外地捕获 BaseException

建议

分别处理 ExceptionKeyboardInterruptSystemExit。不要使用简单的 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

参考资料

  • Python 语言参考:try 语句异常

  • M. Lutz, Learning Python,第 35.3 节:异常设计技巧和陷阱,O’Reilly Media,2013。

  • Python 教程:错误和异常

  • 常见弱点枚举:CWE-396

  • ©GitHub, Inc.
  • 条款
  • 隐私