中的Python sys.exc_info最终打印一个异常,该异常可以';不要被抓住
我有以下代码:中的Python sys.exc_info最终打印一个异常,该异常可以';不要被抓住,python,Python,我有以下代码: import contextlib import sys class CC: def __enter__(self): pass def __exit__(self, *args): return True @contextlib.contextmanager def ctx(): try: with CC(): yield except: pri
import contextlib
import sys
class CC:
def __enter__(self):
pass
def __exit__(self, *args):
return True
@contextlib.contextmanager
def ctx():
try:
with CC():
yield
except:
print("has exception")
raise
finally:
print("finally")
print(sys.exc_info())
def test():
with ctx():
raise ValueError()
test()
这有点复杂。但是我的想法是在上下文ctx
中引发一个异常。因为退出时,CC
返回True
,所以异常应为。因此我希望except
子句不会执行,finally
子句中的sys.exc_info()
不会打印任何内容
但实际情况是,
except
子句不执行,但finally
子句中的sys.exc_info()
打印原始异常。这让我很困惑,因为\uuuuuu exit\uuuuu
返回True不应该抑制异常吗?为什么except
和sys.exc_info()
之间存在差异?我找到了问题的答案
因此,在上下文管理器中(使用@contextmanager
或显式定义的\uuuu退出\uuuuuu
),当出现异常时,它会从产出中抛出。本质上,除了抛出代码的
,其余代码都在中执行。当然,上下文管理器可以捕获并抑制重新引发的异常,但它不会改变它位于except
子句中的事实,因此它仍然在处理原始异常。这意味着即使捕获并抑制了重新引发的异常,sys.exc_info()
仍将显示原始异常
举个例子,这意味着
@contextmanager
def ctx():
try:
try:
yield
except:
pass
except:
assert False
finally:
print(sys.exc_info())
with ctx():
raise ValueError()
将在finally
中打印原始ValueError
,但外部除外
不会捕获任何内容
此外,我认为这意味着上下文管理器并不是代码重构的完全替代品
with ctx:
try:
foo()
except:
...
不能总是转化为
@contextmanager
def fun():
with ctx:
try:
yield
except:
...
with fun():
do_something()