在上下文管理器中捕获异常__enter __() [英] Catching exception in context manager __enter__()

查看:162
本文介绍了在上下文管理器中捕获异常__enter __()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有可能确保 __ exit __()方法即使在 __中有异常__输入__()

 >>> class TstContx(object):
... def __enter __(self):
... raise Exception('Oops in __enter__')
...
... def __exit __(self,e_typ,e_val,trcbak):
... print这不运行
...
>>>使用TstContx():
... pass
...
追溯(最近的最后一次调用):
文件< stdin>,第1行,模块>
文件< stdin>,第3行,__enter__
例外:在__enter__
>>>

修改



这是尽可能接近...

  class TstContx(object):
def __enter __自我):
尝试:
#__enter__代码
除了例外作为e
self.init_exc = e

返回自我

def __exit __(self,e_typ,e_val,trcbak):
如果全部((e_typ,e_val,trcbak)):
raise e_typ,e_val,trcbak

#__exit__代码


with TstContx()as tc:
if hasattr(tc,'init_exc'):raise tc.init_exc

# b $ b

在后视中,上下文管理器可能尚未成为最佳设计决策

解决方案

像这样:

  import sys 

类上下文(对象):
def __enter __(self):
try:
raise异常(哎呀在__ente
除了:
#如果__exit__返回一个真值,则运行异常
如果self .__ exit __(* sys.exc_info()):
pass
else:
raise


def __exit __(self,e_typ,e_val,trcbak):
print现在运行


with Context():
pass

让程序继续快乐的方式没有执行上下文块,您需要检查上下文块中的上下文对象,并且只有在 __输入__ 成功时才能执行重要的操作。



$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $

$ b $ _ $($) :
try:
raise异常(哎呀在__enter__)
除了:
如果self .__退出__(* sys.exc_info()):
self.enter_ok = False
else:



def __exit __(self,e_typ,e_val,trcbak):
print现在运行两次
return True


与Context()作为c:
如果c.enter_ok:
打印仅在输入成功时运行

print执行继续

据我所知,您无法完全跳过with-block。并注意到这个上下文现在吞下了所有的例外。如果您不想吞下异常,如果 __输入__ 成功,请在 __ exit __ 中检查 self.enter_ok / code>和 return False 如果它是 True


Is it possible to ensure the __exit__() method is called even if there is an exception in __enter__()?

>>> class TstContx(object):
...    def __enter__(self):
...        raise Exception('Oops in __enter__')
...
...    def __exit__(self, e_typ, e_val, trcbak):
...        print "This isn't running"
... 
>>> with TstContx():
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __enter__
Exception: Oops in __enter__
>>> 

Edit

This is as close as I could get...

class TstContx(object):
    def __enter__(self):
        try:
            # __enter__ code
        except Exception as e
            self.init_exc = e

        return self

    def __exit__(self, e_typ, e_val, trcbak):
        if all((e_typ, e_val, trcbak)):
            raise e_typ, e_val, trcbak

        # __exit__ code


with TstContx() as tc:
    if hasattr(tc, 'init_exc'): raise tc.init_exc

    # code in context

In hind sight, a context manager might have not been the best design decision

解决方案

Like this:

import sys

class Context(object):
    def __enter__(self):
        try:
            raise Exception("Oops in __enter__")
        except:
            # Swallow exception if __exit__ returns a True value
            if self.__exit__(*sys.exc_info()):
                pass
            else:
                raise


    def __exit__(self, e_typ, e_val, trcbak):
        print "Now it's running"


with Context():
    pass

To let the program continue on its merry way without executing the context block you need to inspect the context object inside the context block and only do the important stuff if __enter__ succeeded.

class Context(object):
    def __init__(self):
        self.enter_ok = True

    def __enter__(self):
        try:
            raise Exception("Oops in __enter__")
        except:
            if self.__exit__(*sys.exc_info()):
                self.enter_ok = False
            else:
                raise
        return self

    def __exit__(self, e_typ, e_val, trcbak):
        print "Now this runs twice"
        return True


with Context() as c:
    if c.enter_ok:
        print "Only runs if enter succeeded"

print "Execution continues"

As far as I can determine, you can't skip the with-block entirely. And note that this context now swallows all exceptions in it. If you wish not to swallow exceptions if __enter__ succeeds, check self.enter_ok in __exit__ and return False if it's True.

这篇关于在上下文管理器中捕获异常__enter __()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆