Python中的文件句柄在超出作用域后会自动关闭吗?

27
如果我执行以下操作,在Python中,文件句柄会在超出作用域时自动关闭吗?
def read_contents(file_path):
  return file(file_path).read()

如果不行,我该如何编写这个函数以自动关闭作用域?

2个回答

42
进一步解释FogleBird的答案,如果你不明确地关闭文件,那么当文件对象被销毁时,它将会自动关闭。在CPython中,只要没有对其的引用,例如它是函数中的局部变量,而函数结束了,它就会被关闭。然而,如果函数中抛出异常且文件没有使用with语句或try:...finally:来明确关闭,则文件的引用将作为堆栈跟踪的一部分保留在traceback对象中,文件将不会关闭,至少直到下一个异常被抛出。
此外,IronPython和Jython使用.Net CLR和Java JVM的垃圾回收设施。这些不是引用计数的,因此文件将一直保持打开状态,直到垃圾收集器决定回收对象的内存或程序终止。
因此,通常重要的是要使用with:try:...finally:明确关闭文件。
当然,所有这些都适用于需要明确清理的任何其他类型的对象。

1
"没在意" - 我之前不知道这些。 :( - bodacydo
2
另外请注意:在Python 3中,“文件不会被关闭,至少直到下一个异常被抛出”这个条款已经不再准确;在Python 3中,引发新异常隐式地链接了异常上下文,因此如果您捕获了一个异常并引发了一个新的异常,则原始异常的回溯信息将保留在新异常中(除非他们明确禁用了上下文,例如通过引发“from None”)。在Py 2和3中,通过traceback很容易创建循环垃圾;即使异常不再被引用,您最终仍然需要等待循环GC进行清理,就像Jython一样。 - ShadowRanger

21

仅提及一下:文件返回一个具有close方法的文件对象。这可能是最直接的解决方案,但“with”显然更好。 - Achim
我有一个问题 - 我的Python中没有with。从future导入可以吗?我使用的是Python 2.5。 - bodacydo
如果你有Python 2.5,那么是的。 - Tim Pietzcker
谢谢。还有一个问题 - 如果我将我的应用程序转移到使用Python 2.6进行安装,那么import with from future是否仍然有效? - bodacydo
如果返回f本身会发生什么?那个文件句柄会一直保持打开状态,直到所有对它的引用都丢失吗?还是移出with作用域会自动关闭句柄,并将一个(可能无用的)关闭句柄返回给调用者? - davidA
显示剩余2条评论

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