如何通过Signal处理Python未预期致命错误并执行清理操作?
解决Python异常/崩溃时的相机资源清理问题
问题本质
你用信号处理函数无法捕获AttributeError这类异常,是因为Python层面的未捕获异常不会触发系统信号——信号处理只针对系统级事件(比如Ctrl+C触发SIGINT、进程被kill触发SIGTERM),而像拼写错误、属性不存在这类代码错误属于Python运行时异常,走的是Python自身的异常处理流程。
要实现“无论程序怎么崩溃都执行camera.stop()”,需要同时覆盖系统信号中断和Python未捕获异常两种场景,下面是两种可行方案:
方案一:try-except包裹主逻辑
把所有业务代码放在try块中,用except捕获所有未处理异常,同时用finally保证正常退出时也执行清理,再配合信号处理覆盖系统级中断。
import signal import sys def cleanup(): # 这里替换成实际的相机清理逻辑 print("执行camera.stop()清理相机资源") def signal_handler(signum, frame): cleanup() sys.exit(0) # 注册系统信号处理 signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGHUP, signal_handler) signal.signal(signal.SIGABRT, signal_handler) if __name__ == "__main__": try: # 你的主业务逻辑,比如相机初始化、运行 print("a{}".format()) # 故意写错方法名,触发AttributeError except Exception as e: print(f"捕获到异常: {str(e)}") cleanup() sys.exit(1) finally: # 正常退出时也会执行清理 cleanup()
方案二:重写全局异常钩子sys.excepthook
如果你不想把所有代码套在try里,可以重写Python的全局异常钩子,它会在出现未捕获异常时自动触发,同时保留信号处理覆盖系统级场景。
import signal import sys def cleanup(): # 实际的相机清理操作 print("执行camera.stop()释放相机资源") def signal_handler(signum, frame): cleanup() sys.exit(0) # 注册系统信号处理 signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGHUP, signal_handler) signal.signal(signal.SIGABRT, signal_handler) # 自定义全局异常处理钩子 def custom_excepthook(exc_type, exc_value, exc_traceback): # 先打印默认的错误栈(可选,方便调试) sys.__excepthook__(exc_type, exc_value, exc_traceback) # 执行清理逻辑 cleanup() sys.exit(1) # 替换默认的异常钩子 sys.excepthook = custom_excepthook if __name__ == "__main__": print("a{}".fomrat()) # 触发AttributeError,触发自定义钩子
效果验证
两种方案结合后,不管是用户按Ctrl+C(触发SIGINT)、进程被外部终止(SIGTERM),还是代码写错导致的AttributeError/IndexError等异常,都会自动执行cleanup()里的相机停止操作,避免资源被锁死需要重启设备。
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan
相关产品推荐
相关产品推荐

