有没有办法防止捕获从sys.exit()引发的SystemExit异常



文档说,调用sys.exit()会引发SystemExit异常,该异常可以在外部级别中捕获。在这种情况下,我想明确无疑地从测试用例内部退出,但是单元测试模块捕获SystemExit并阻止退出。这通常很好,但我试图处理的具体情况是,我们的测试框架检测到它被配置为指向非测试数据库。在这种情况下,我想退出并阻止任何进一步的测试运行。当然,由于unittest捕获了SystemExit并愉快地继续前进,它正在挫败我

到目前为止,我唯一想到的选择是使用ctypes或类似于直接调用exit(3)的方法,但这似乎是一个非常简单的方法。

您可以调用os._exit()直接退出,而不会抛出异常:

import os
os._exit(1)

这将绕过所有python关闭逻辑,例如atexit模块,并且不会运行您在这种情况下试图避免的异常处理逻辑。参数是进程将返回的退出代码。

正如Jerub所说,os._exit(1)就是你的答案。但是,考虑到它绕过了所有清理过程,包括finally:块、关闭文件等,确实应该不惜一切代价避免它。那么,我可以介绍一种更安全的使用方法吗?

如果你的问题是SystemExit在外层被捕获(即单元测试),那么自己就是外层将主代码封装在try/except块中,捕获SystemExit,然后在那里调用os._exit(),在那里只调用这样,您可以在代码中的任何位置正常调用sys.exit,让它冒泡到顶层,优雅地关闭所有文件并运行所有清理,然后调用os._exit

您甚至可以选择哪些出口是";"紧急情况";一个。下面的代码就是这种方法的一个例子:

import sys, os
EMERGENCY = 255  # can be any number actually
try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    ...  # yes, this is valid python!
    # Might instead wrap all code in a function
    # It's a common pattern to exit with main's return value, if any
    sys.exit(main())
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it at the outer level
else:
    os._exit(EMERGENCY)  # try to stop *that*!

至于一些读者不知道的e.code,它被记录下来,以及所有内置异常的属性。

相关内容

  • 没有找到相关文章

最新更新