如何在使用with和try..except时关闭文件?

18 浏览
0 Comments

如何在使用with和try..except时关闭文件?

此问题在这里已经有答案了:

在Python的自定义类中实现使用 \'with object() as f\'

我写了这个例子来证明当异常发生时,__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__呢?

谢谢!

admin 更改状态以发布 2023年5月22日
0
0 Comments

无论是否在with主体中引发错误,__exit__函数都会被调用。您的函数需要具有额外的参数exc_type(异常的类型),exc_value(异常对象)和traceback(生成的追溯)。\n\n如果with主体没有引发Error,则这三个参数的值为None。如果存在错误,则它们采用上述描述的值。\n\n但是,您可以关闭文件,而不管是否存在错误,然后稍后处理错误。\n\n因此,例如,我们可以将其实现为:\n\n

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?

\n\n现在如果我们写一些像这样的东西:\n\n

with A():
    raise Exception

\n\n我们会得到异常,__exit__函数将会打印:\n\n

('exit', , Exception(), )

\n\n我们可以检查异常类、异常值和追溯,然后进行相应的处理。例如,基于异常,我们可能决定关闭文件、发送错误报告、中止SQL事务或不这样做。\n\n__exit__函数还具有返回值(如果没有指定,则Python函数返回None)。如果__exit__函数返回具有真值True的对象,则它将抑制异常:异常不会在with块外引发。否则,它将在with块外引发。例如,在我们的示例中,我们仍然收到异常。\n\n

class SilenceExceptions(object):
    def __enter__(self):
        pass
    def __exit__(self, exc_type, exc_value, traceback):
        return True  # silence ALL exceptions

\n\n如果我们现在调用:\n\n

with SilenceExceptions():
    raise Error

\n\n我们不会看到异常,因为它被“捕获”在__exit__函数中。

0