如何在上下文管理器的 __exit__ 中操作异常? [英] How to manipulate the exception in __exit__ of a context manager?
问题描述
我知道从上下文管理器的 __exit__()
方法中重新引发异常是一种糟糕的风格.因此,我想在实例上添加一个属性,该属性可以携带上下文信息,如果我让异常涓涓细流或捕获它,则该属性将不可用.这将避免重新加注.
在异常上添加属性的替代方法是吞下异常,在兼作相关上下文管理器的实例上设置一些状态,然后检查该状态.问题是这会导致捕获 22,不是吗?由于异常意味着正在退出 with
块内的执行.除了再次进入with
块,没有办法重复操作,对吗?因此,一旦 __exit__()
方法返回,我尝试存储上下文信息的实例就会消失.
简而言之:如何在 __exit__()
方法中操作待处理的实际异常(如果是,我将假设为针对此问题给出的)?>
上下文管理器不会因为块退出而消失.您可以通过两种方式保存它:
首先创建上下文管理器,将其分配给一个变量,然后将
with
用于该对象:cm = ContextManager()与厘米:# ....状态 = cm.attribute
从
__enter__
方法返回上下文管理器本身,使用with ... as ...
将其绑定到本地名称.with
退出时,该名称未绑定:使用 ContextManager() 作为 cm:# ....状态 = cm.attribute
其中
ContextManager.__enter__
使用return self
.
您还可以为异常本身设置额外的属性;无需重新引发异常:
<预><代码>>>>类上下文管理器(对象):... def __enter__(self):... 回归自我... def __exit__(self, tp, v, tb):...如果 tp 为 None:返回... v.extra_attribute = 'foobar'... self.other_extra_attribute = 'spam-n-ham'...>>>尝试:...与 ContextManager() 作为厘米:... 引发 ValueError('barfoo')... 除了 ValueError 如:... 打印变量(例如)...{'extra_attribute': 'foobar'}>>>变量(厘米){'other_extra_attribute': '垃圾邮件'}这里异常被赋予了一个额外的属性,该属性一直持续到异常处理程序.在上面我还表明 cm
仍然绑定到上下文管理器.
I know it's bad style to re-raise an exception from within a context manager's __exit__()
method. So, I'd like to tack an attribute on the instance which can carry contextual information that isn't available if I let the exception trickle through or if I catch it. This will avoid re-raising it.
The alternative to tacking the attribute on the exception would be to swallow the exception, set some state on the instance that doubles as the context manager in question and later check that state. Problem is that this would lead to a catch 22, wouldn't it? Since the exception means that execution inside the with
block is being exited. There is no way to repeat the operation other than entering the with
block again, right? So the instance in which I am trying to store the contextual information would go away once the __exit__()
method returns.
So in short: how can I manipulate the actual exception that is pending (if it is, which I'll assume as given for this question) while in the __exit__()
method?
The context manager doesn't go away just because the block exits. You can preserve it in two ways:
Create the context manager first, assign it to a variable, then use
with
with that object:cm = ContextManager() with cm: # .... state = cm.attribute
Return the context manager itself from the
__enter__
method, usewith ... as ...
to bind that to a local name. That name is not unbound whenwith
exits:with ContextManager() as cm: # .... state = cm.attribute
where
ContextManager.__enter__
usesreturn self
.
You can also set extra attributes on the exception itself; no need to re-raise the exception:
>>> class ContextManager(object):
... def __enter__(self):
... return self
... def __exit__(self, tp, v, tb):
... if tp is None: return
... v.extra_attribute = 'foobar'
... self.other_extra_attribute = 'spam-n-ham'
...
>>> try:
... with ContextManager() as cm:
... raise ValueError('barfoo')
... except ValueError as ex:
... print vars(ex)
...
{'extra_attribute': 'foobar'}
>>> vars(cm)
{'other_extra_attribute': 'spam-n-ham'}
Here the exception was given an extra attribute that persisted all the way to the exception handler. In the above I also show that cm
is still bound to the context manager.
这篇关于如何在上下文管理器的 __exit__ 中操作异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!