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

时间:2008-10-06 05:40:14

标签: python exception exit systemexit

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

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

3 个答案:

答案 0 :(得分:70)

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

import os
os._exit(1)

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

答案 1 :(得分:46)

正如杰罗布所说,os._exit(1)是你的答案。但是,考虑到它绕过所有清理程序,包括finally:块,关闭文件等,并且应该不惜一切代价避免,我可以提出一种“更安全”的使用方式它?

如果你的问题是SystemExit被外层攻击(即unittest),那么 就是你自己的外层! 将你的主要代码包裹在一个try / except block,catch 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
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!

答案 2 :(得分:0)

您也可以使用quit,请参见以下示例:

while True:
print('Type exit to exit.')
response = input()
if response == 'exit':
    quit(0)
print('You typed ' + response + '.')