关于python:是否有方法防止捕获从sys.exit()引发的SystemExit异常?

Is there a way to prevent a SystemExit exception raised from sys.exit() from being caught?

文档说调用sys.exit()会引发一个SystemExit异常,这种异常可以在外部级别捕获。我有一种情况,在这种情况下,我希望从测试用例内部明确地、毫无疑问地退出,但是UnitTest模块捕获SystemExit并阻止退出。这通常很好,但我尝试处理的具体情况是,我们的测试框架检测到它配置为指向非测试数据库。在这种情况下,我希望退出并阻止运行任何进一步的测试。当然,由于UnitTest捕获了系统出口并继续沿着它的方式愉快地运行,所以它阻碍了我。

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


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

1
2
import os
os._exit(1)

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


如耶路伯所说,以东十一〔二〕是你的回答。但是,考虑到它绕过了所有清理过程,包括finally:块、关闭文件等,并且应该不惜一切代价避免,我可以介绍一种"更安全"的使用方法吗?

如果你的问题是SystemExit被困在外部层面(即unittest),那么你自己就是外部层面!将主代码包装在一个try/except块中,捕获SystemExit,然后调用OS。退出那里,只在那里!通过这种方式,您可以在代码中的任何地方正常调用sys.exit,让它冒泡到顶层,优雅地关闭所有文件并运行所有清理,然后调用OS。_exit。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!