如何在__init__期间调用异常__exit__方法?

时间:2013-07-01 19:41:33

标签: python python-2.7

假设您有一个定义了__enter____exit__方法的类,如下所示:

class MyClass:
    def f(self):
        raise Exception
    def __enter__(self): 
        return self
    def __exit__(self, type, value, traceback):
        pass

如果在with块内引发异常,则如下:

with MyClass() as ins:
    ins.f()

将隐式调用__exit__方法,这非常好。

但是,如果你的课程是这样的:

class MyClass:
    def __init__(self):
        self.f()
    def f(self):
        raise Exception
    def __enter__(self): 
        return self
    def __exit__(self, type, value, traceback):
        pass

你实例化它是这样的:

with MyClass() as ins:
    pass

__init__方法中引发异常时,__enter__尚未被调用,__exit__也未被调用,这不太好。解决这个问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:4)

显然,您不能使用无法作为上下文管理器启动的类,因此您必须先创建实例,然后才能在with块中使用它。

例如:

try:
    ins = MyClass()
except Exception as e: 
    print "Cant initiate MyClass"
else:
    with ins:
        pass

您可以通过将额外资源传递给Class而不是在启动期间创建它们来添加额外资源:

with spawnResource() as res, MyClass(res) as y:
    print x,y

答案 1 :(得分:2)

像其他人指出的那样,没有干净的方式,因为你试图做的事情很尴尬。

直截了当的方式是:

  

如果您想在__exit__中清理一些内容,请将其初始化   __enter__

E.g。

class MyClass:
    def f(self):
        raise Exception
    def __enter__(self):
        print 'in __enter__'
        # acquire it here...
        return self
    def __exit__(self, type, value, traceback):
        print 'in __exit__'
        # release it here...

with MyClass() as ins:
    print 'calling f()'
    ins.f()