我写这个例子是为了告诉我自己在发生异常时没有运行__exit__
:
class A(object):
def __enter__(self):
print('enter')
def __exit__(self):
print('exit')
try:
with A() as a:
raise RunTimeError()
except Exception as e:
print('except')
输出:
enter
except
那就是说,使用with
语句并捕获异常的正确方法是什么,同时确保最终运行__exit__
?
谢谢!
答案 0 :(得分:3)
__exit__
函数被称为,无论with
正文是否引发错误。您的函数需要有其他参数exc_type
(异常的类型),exc_value
(异常对象)和traceback
(生成的回溯)。
如果with
正文不提出Error
,则三个参数为None
。如果出现错误,则采用上述值。
但是你可以关闭一个文件,无论是否有错误,然后再处理错误。
所以我们可以在这里实现它:例如:
class A(object):
def __enter__(self):
self.file = open('some_file.txt')
return self.file
def __exit__(self, exc_type, exc_value, traceback):
print(('exit', exc_type, exc_value, traceback))
# close the file, regardless of exceptions
self.file.close()
return False # silence the exception?
如果我们现在写下这样的话:
with A():
raise Exception
我们将获得例外,__exit__
函数将打印:
('exit', <class 'Exception'>, Exception(), <traceback object at 0x7fc512c924c8>)
我们可以检查异常类,异常值和回溯,并相应地处理。例如,基于异常,我们可能决定关闭文件,发送错误报告,中止SQL事务。
__exit__
函数也有一个返回值(如果没有指定,Python函数返回None
)。如果__exit__
函数返回一个真实性 True
的对象,它将压制异常:异常不会从{{{{ 1}}阻止。否则它将被提升出with
块。例如,在我们的示例中,我们仍然收到异常。
with
如果我们现在打电话:
class SilenceExceptions(object):
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
return True # silence ALL exceptions
我们不会看到异常,因为它是with SilenceExceptions():
raise Error
函数中的“ catched ”。