3

有没有一种方法可以在上下文管理器的方法中捕获异常,__enter__而无需将整个with块包装在 a中try

class TstContx(object):
    def __enter__(self):
        raise Exception("I'd like to catch this exception")
    def __exit__(self, e_typ, e_val, trcbak):
        pass


with TstContx():
    raise Exception("I don't want to catch this exception")
    pass

我知道我可以在__enter__()自身内部捕获异常,但是我可以从包含该with语句的函数中访问该错误吗?

从表面上看,在上下文管理器中捕获异常__enter__()的问题似乎是一回事,但这个问题实际上是关于确保__exit__调用它,而不是与语句所包含__enter__的块不同地处理代码。with

...显然动机应该更清楚。该with声明正在为一个完全自动化的过程设置一些日志记录。如果程序在日志设置之前失败,那么我不能依靠日志来通知我,所以我必须做一些特别的事情。而且我宁愿在不必添加更多缩进的情况下实现效果,如下所示:

try:
    with TstContx():
        try:
            print "Do something"
        except Exception:
            print "Here's where I would handle exception generated within the body of the with statement"
except Exception:
    print "Here's where I'd handle an exception that occurs in __enter__ (and I suppose also __exit__)"

使用两个try块的另一个缺点是处理异常__enter__的代码在块的后续主体中处理异常的代码之后with

4

2 回答 2

3

try您可以使用/ exceptinside of捕获异常__enter__,然后将异常实例保存为TstContx类的实例变量,允许您在块内访问它with

class TstContx(object):
    def __enter__(self):
        self.exc = None
        try:
            raise Exception("I'd like to catch this exception")
        except Exception as e:
            self.exc = e 
        return self

    def __exit__(self, e_typ, e_val, trcbak):
        pass    

with TstContx() as tst:
    if tst.exc:
        print("We caught an exception: '%s'" % tst.exc)
    raise Exception("I don't want to catch this exception")

输出:

We caught an exception: 'I'd like to catch this exception'.
Traceback (most recent call last):
  File "./torn.py", line 20, in <module>
    raise Exception("I don't want to catch this exception")
Exception: I don't want to catch this exception

不知道你为什么要这样做,虽然......

于 2014-07-22T03:56:56.347 回答
0

您可以contextlib.ExitStack按照此文档示例中的说明使用,以便分别检查__enter__错误:

from contextlib import ExitStack

stack = ExitStack()
try:
    stack.enter_context(TstContx())
except Exception:  # `__enter__` produced an exception.
    pass
else:
    with stack:
        ...  # Here goes the body of the `with`.
于 2020-11-04T09:28:04.997 回答