<分区>
我经常看到这种代码:
filecontent = open(thefilename).read()
我想知道在这种情况下 open
创建的文件对象是什么:它是隐式关闭的,还是在某处保持打开状态?
标签 python file python-3.x
<分区>
我经常看到这种代码:
filecontent = open(thefilename).read()
我想知道在这种情况下 open
创建的文件对象是什么:它是隐式关闭的,还是在某处保持打开状态?
最佳答案
I wonder what becomes the file object created by open in this situation: is it implicitly closed, or does it stay open somewhere ?
它一直保持打开状态,直到垃圾收集器发现没有人可以再访问它并销毁它,此时它被析构函数关闭。
Python 语言不保证什么时候会发生(当然,除非是在您无法再访问它之后)。
但是,CPython 实现(您可能正在使用它,因为截至 2013 年 5 月,它是唯一可用的 3.x 实现)使用引用计数(加上循环检测器)进行垃圾收集,这意味着一旦最后一个引用消失了(除非它在某个时候参与了一个循环),对象被销毁。
因此,在 CPython 中,在大多数情况下,一旦您从函数返回,将新值分配给 filecontent
或 del filecontent
,文件就会立即关闭.很多快速而肮脏的代码都依赖于此。
但 Jython 和 IronPython 依赖于 Java/.NET 垃圾收集器,它以复杂而奇特的方式定期检查垃圾,而不是动态跟踪,因此无法保证何时收集任何东西。 PyPy 有多个选项,具体取决于它的配置方式。
而且,即使在 CPython 中,在没有可见 引用之后,垃圾也有可能留在周围,因为,例如,您在调试器中运行它并最终得到一些不可见 引用文献。或者,如果文件涉及引用循环,它可能永远不会关闭。
所以,除了快速和肮脏的代码之外,你不应该在任何地方依赖这种行为。基本上,如果文件在您的程序完成之前保持打开状态是可以接受的,那很好。否则,不要这样做。
正确的方法是使用 with
语句:
with open(thefilename) as f:
filecontent = f.read()
这保证 f.close()
在 with
语句完成后立即被调用。
人们经常会建议一种将其变成单行代码的方法,Guido 总是这样回答,“with open(thefilename) as f: filecontent = f.read()
已经是单行代码了。它有点糟糕,但远没有你建议的那么糟糕。”
但实际上,有一个更好的答案:编写一个包装它的函数:
def read_whole_file(filename):
with open(thefilename) as f:
return f.read()
然后:
filecontent = read_whole_file(thefilename)
干净、简洁、可读……没有任何借口可以“打开
”,让 GC 将它们分类出来。
关于python - 文件是否关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16405926/