【问题标题】:How to find exit code or reason when atexit callback is called in Python?在 Python 中调用 atexit 回调时如何查找退出代码或原因?
【发布时间】:2012-03-16 16:53:48
【问题描述】:

我想知道 Python 脚本是否正确终止。为此,我使用atexit,但问题是我不知道如何区分atexit 是使用sys.exit(0) 还是非零或异常调用的。

推理:如果程序正常结束,它什么也不做,但如果程序以异常结束或返回不同于零的错误代码(退出状态)我想触发一些动作。

如果您想知道为什么我不使用 try/finally 是因为我想为导入公共模块的十几个脚本添加相同的行为。我不想修改所有这些,而是​​想将 atexit() hack 添加到正在导入的模块中,并在所有这些模块中免费获得此行为。

【问题讨论】:

    标签: python atexit


    【解决方案1】:

    您可以使用sys.excepthook 和猴子补丁sys.exit() 解决此问题:

    import atexit
    import sys
    
    class ExitHooks(object):
        def __init__(self):
            self.exit_code = None
            self.exception = None
    
        def hook(self):
            self._orig_exit = sys.exit
            sys.exit = self.exit
            sys.excepthook = self.exc_handler
    
        def exit(self, code=0):
            self.exit_code = code
            self._orig_exit(code)
    
        def exc_handler(self, exc_type, exc, *args):
            self.exception = exc
    
    hooks = ExitHooks()
    hooks.hook()
    
    def foo():
        if hooks.exit_code is not None:
            print("death by sys.exit(%d)" % hooks.exit_code)
        elif hooks.exception is not None:
            print("death by exception: %s" % hooks.exception)
        else:
            print("natural death")
    atexit.register(foo)
    
    # test
    sys.exit(1)
    

    【讨论】:

    • @sorin:对我来说效果很好。我将钩子函数包装在一个类中(它不会改变功能)并添加了sys.exit(1)。它在 Python 2.7 上为我打印 sys.exit(1)
    • @sorin:你可能忘记了global exit_code 里面的patched_exit 吗?起初我忘记了,但在发布答案后立即对其进行了编辑。
    • @sorin:我只是切换到一个类来避免全局变量,机制是完全一样的。如果你检查旧版本,它应该也能正常工作(至少对我来说是这样)。
    • 这似乎使回溯 stdout/err 消失了。有没有办法保留回溯,只需添加打印语句?
    • @e9t 我在这里玩游戏迟到了,但刚开始使用它并遇到了您的问题。您需要捕获原始的异常钩子,然后调用它。基本上这个解决方案对 sys.exit 做了什么,但对 sys.excepthook
    猜你喜欢
    • 1970-01-01
    • 2019-08-03
    • 2021-10-16
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多