保证文件关闭

5
我有一个类,在构造函数中创建了一个文件对象。该类还实现了一个finish()方法作为其接口的一部分,在此方法中关闭文件对象。问题是,如果在这一点之前出现异常,则文件将不会被关闭。该类有许多其他使用文件对象的方法。我需要将所有这些方法都包装在try finally子句中吗?还是有更好的方法?
谢谢,
Barry

这基本上就是为什么try...finally被创建的原因。 - Oliver
是的,您需要将其包装在try子句中。但是您已经提到了其他引用相同对象的方法,您能否详细说明一下? - unni
3个回答

11
你可以将你的类变成一个上下文管理器(context-manager),并在 with 语句中包装对象的创建和使用。详情请参见PEP 343
要将你的类变成上下文管理器,它必须实现方法__enter__()__exit__()。 当进入 with 语句时调用__enter__(),并且无论如何离开时都保证调用__exit__()
然后你可以像这样使用你的类:
with MyClass() as foo:
    # use foo here

如果您在构造函数中获取资源,则可以使__enter__()方法简单地返回self而不执行任何操作。__exit__()方法应该只调用您的finish()方法。


1
+1 还有contextlib.contextmanager,用于创建上下文管理器,以处理不需要额外类的事情。 (我必须挑剔一下:不需要 do - 即:语法错误) - user395760
2
@delnan 或者只需在 close 实例方法中调用 file_handle.close() 并使用 contextlib.closing。(已删除 do - agf
是的,那是另一种选择 - 虽然在使用场景中它更加丑陋,特别是因为它需要到处导入contextlib。我并不打算针对这个具体例子建议使用contextlib.contextmanager,我只是认为提及它会很有用,因为有些情况下其他方法并不那么干净利落。 - user395760

3
对于短暂的文件对象,建议使用try/finally对或更简洁的with语句来确保文件被刷新并释放相关资源。
对于长期存在的文件对象,您可以通过atexit()注册一个显式关闭,或者只是依赖解释器在退出之前进行清理。
在交互式提示符下,大多数人不会为简单的实验费心去关闭文件,因为留下未关闭的文件或依赖refcounting或GC为您关闭文件并没有太大的副作用。
关闭文件被认为是良好的技巧。然而,在现实中,不明确关闭文件很少有任何明显的影响。

雷蒙德 - 关闭已打开的写入文件怎么样?我想每次写入时都不能保证刷新,直到文件被关闭?如果一个类的职责是写入文件,然后由某个其他实体(在进程的运行时)读取该文件,那么保证文件被关闭可能非常重要。 - Eli Bendersky
1
对于写操作而言,关闭文件比读操作更为重要,即使只是为了刷新缓冲区。话虽如此,如果你忘记关闭文件,也不会像小狗一样死掉;-) 许多短暂的脚本在解释器退出之前关闭所有内容都能正常工作--好的技巧是关闭文件但不要过于担心--这并不是一个致命的错误。 - Raymond Hettinger

1

你可以使用 try...finally 语句块,或将你的类设计为适用于 with 语句的上下文管理器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接