How to manipulate the exception in __exit__ of a context manager?

为君一笑 提交于 2019-12-03 08:23:09

The context manager doesn't go away just because the block exits. You can preserve it in two ways:

  1. Create the context manager first, assign it to a variable, then use with with that object:

    cm = ContextManager()
    with cm:
        # ....
    
    state = cm.attribute
    
  2. Return the context manager itself from the __enter__ method, use with ... as ... to bind that to a local name. That name is not unbound when with exits:

    with ContextManager as cm:
        # ....
    
    state = cm.attribute
    

    where ContextManager.__enter__ uses return 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!