文件已关闭吗?

mic*_*yer 4 python file python-3.x

我经常看到这种代码:

filecontent = open(thefilename).read()
Run Code Online (Sandbox Code Playgroud)

我想知道open在这种情况下创建的文件对象是什么:它是隐式关闭的,还是在某个地方保持打开状态?

aba*_*ert 12

我想知道在这种情况下open会创建的文件对象是什么:它是隐式关闭的,还是在某个地方保持打开状态?

它一直保持打开状态,直到垃圾收集器发现任何人都无法访问它并销毁它,此时它被析构函数关闭.

Python语言不保证何时会发生这种情况(当然,除非你不能再访问它).

但是,CPython实现(您可能正在使用它,因为它是截至2013年5月唯一可用的3.x实现)使用引用计数(加上循环检测器)进行垃圾收集,这意味着最后一次引用消失(除非它在某个时刻涉及一个循环),物体被摧毁.

因此,在CPython中,在大多数情况下,文件将在您从函数返回后立即关闭,为其分配新值filecontentdel filecontent.许多快速和脏代码都依赖于此.

但是Jython和IronPython依赖于Java/.NET垃圾收集器,垃圾收集器以复杂和奇特的方式定期检查垃圾,而不是动态跟踪,因此无法确保何时收集任何内容.PyPy有多种选择,具体取决于它的配置方式.

而且,即使在CPython中,垃圾也可能在没有可见引用之后保持不变,因为例如,您在调试器中运行它并最终得到一些不可见的引用.或者,如果文件涉及参考周期,则可能永远不会关闭.

因此,除了快速和脏代码之外,您不应该依赖于此行为.基本上,如果在程序完成之前文件保持打开是可以接受的,那很好.否则,不要这样做.

正确的做到这一点的方法是使用一个with语句:

with open(thefilename) as f:
    filecontent = f.read()
Run Code Online (Sandbox Code Playgroud)

这保证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()
Run Code Online (Sandbox Code Playgroud)

然后:

filecontent = read_whole_file(thefilename)
Run Code Online (Sandbox Code Playgroud)

干净,简洁,可读......没有任何理由" open所有人都让GC排除他们"黑客.