假设您有一个定义了__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__
也未被调用,这不太好。解决这个问题的最佳方法是什么?
答案 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()