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

蓝咒 提交于 2019-11-26 09:25:35

问题


The docs say that calling sys.exit() raises a SystemExit exception which can be caught in outer levels. I have a situation in which I want to definitively and unquestionably exit from inside a test case, however the unittest module catches SystemExit and prevents the exit. This is normally great, but the specific situation I am trying to handle is one where our test framework has detected that it is configured to point to a non-test database. In this case I want to exit and prevent any further tests from being run. Of course since unittest traps the SystemExit and continues happily on it\'s way, it is thwarting me.

The only option I have thought of so far is using ctypes or something similar to call exit(3) directly but this seems like a pretty fugly hack for something that should be really simple.


回答1:


You can call os._exit() to directly exit, without throwing an exception:

import os
os._exit(1)

This bypasses all of the python shutdown logic, such as the atexit module, and will not run through the exception handling logic that you're trying to avoid in this situation. The argument is the exit code that will be returned by the process.




回答2:


As Jerub said, os._exit(1) is your answer. But, considering it bypasses all cleanup procedures, including finally: blocks, closing files, etc, and should really be avoided at all costs, may I present a "safer-ish" way of using it?

If you problem is SystemExit being caught at outer levels (ie, unittest), then be the outer level yourself! Wrap your main code in a try/except block, catch SystemExit, and call os._exit there, and only there! This way you may call sys.exit normally anywhere in the code, let it bubble out to the top level, gracefully closing all files and running all cleanups, and then calling os._exit.

You can even choose which exits are the "emergency" ones. The code below is an example of such approach:

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!


来源:https://stackoverflow.com/questions/173278/is-there-a-way-to-prevent-a-systemexit-exception-raised-from-sys-exit-from-bei

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!