Issue
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?
Solution
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.
Answered By - Martijn Pieters
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.