finally块嵌套Try-except:如何正确记录第二个异常
问题描述
你的代码现在存在异常上下文干扰的问题:主try块抛出ProcessError后,你在except块直接raise重新抛出原异常,但进入finally块执行锁操作时,新抛出的ProcessError被捕获后,e.stderr显示的却是原异常的信息,而非finally块里新产生的异常内容。
具体场景:
- 主逻辑
yield抛出:ProcessError("Error retrieving service-id 'test-id'") - finally块执行锁操作抛出:
ProcessError("Error locking service-id 'test-id'") - 实际日志里记录的是原异常的错误信息,不是finally块的新异常内容
解决方案
解决核心是切断原异常的上下文关联,避免它干扰finally块里新异常的属性读取。修改后的代码如下:
try: yield except ProcessError as original_exc: # 用from None切断原异常的上下文,防止它覆盖finally块的新异常信息 raise original_exc from None finally: try: session.iam(f"service-id-lock '{service_id_name}' -f") except ProcessError as e: logger.warning( f"Unable to lock service id '{service_id_name}' due to the following error {e.stderr}" )
原理说明
Python默认raise重新抛出异常时,会保留原异常的上下文(存在__context__属性中)。当finally块抛出新异常时,这个新异常的属性可能会被原异常的上下文覆盖,导致读取e.stderr时拿到旧异常的内容。
使用raise original_exc from None后,原异常的上下文被彻底切断,finally块捕获的ProcessError就是自身抛出的异常,e.stderr会正确显示新异常的错误信息,同时原异常也会正常向外抛出,完全符合你的需求。
内容的提问来源于stack exchange,提问作者jor2
相关产品推荐
相关产品推荐

