Python 文件关闭了吗?
我经常看到这种代码:Python 文件关闭了吗?,python,file,python-3.x,Python,File,Python 3.x,我经常看到这种代码: filecontent = open(thefilename).read() 我想知道在这种情况下,open创建的文件对象会变成什么:它是隐式关闭的,还是在某个地方保持打开状态 我想知道在这种情况下open创建的文件对象会变成什么:它是隐式关闭的,还是在某个地方保持打开状态 它一直保持打开状态,直到垃圾收集器发现没有人可以再访问它并将其销毁,此时它被析构函数关闭 Python语言不保证何时会发生这种情况(当然,除了在您不能再访问它之后) 然而,CPython实现(您可能正
filecontent = open(thefilename).read()
我想知道在这种情况下,open
创建的文件对象会变成什么:它是隐式关闭的,还是在某个地方保持打开状态
我想知道在这种情况下open创建的文件对象会变成什么:它是隐式关闭的,还是在某个地方保持打开状态
它一直保持打开状态,直到垃圾收集器发现没有人可以再访问它并将其销毁,此时它被析构函数关闭
Python语言不保证何时会发生这种情况(当然,除了在您不能再访问它之后)
然而,CPython实现(您可能正在使用它,因为它是截至2013年5月为止唯一有效的3.x实现)使用引用计数(加上一个循环检测器)进行垃圾收集,这意味着一旦最后一个引用消失(除非它在某个点参与了一个循环),对象就会被销毁
因此,在CPython中,在大多数情况下,只要您从函数返回,为filecontent
或delfilecontent
指定一个新值,文件就会关闭。很多快速脏代码都依赖于此
但是Jython和IronPython依赖于Java/.NET垃圾收集器,它以复杂而奇特的方式定期检查垃圾,而不是动态跟踪,因此无法保证何时收集到任何垃圾。PyPy有多个选项,具体取决于它的配置方式
而且,即使在CPython中,垃圾也有可能在没有可见引用后留在周围,因为,例如,您在调试器中运行垃圾,并最终得到一些不可见的引用。或者,如果文件涉及引用循环,则它可能永远不会关闭
因此,除了quick&dirty代码之外,您不应该在任何事情中依赖这种行为。基本上,如果文件在程序完成之前保持打开状态是可以接受的,则可以。否则,不要这样做
正确的方法是使用with
语句:
with open(thefilename) as f:
filecontent = f.read()
这保证了f.close()
语句完成后会立即调用with
语句
经常有人建议将其转换为一行程序,Guido总是这样回答,“将open(thefilename)作为f:filecontent=f.read()
已经是一行程序了。这有点糟糕,但远没有你建议的那么糟糕。”
但实际上,还有一个更好的答案:编写一个封装它的函数:
def read_whole_file(filename):
with open(thefilename) as f:
return f.read()
然后:
filecontent = read_whole_file(thefilename)
干净、简洁、易读……没有理由“打开所有对象并让GC对其进行排序”黑客攻击。一般来说,对象根本不需要收集。在CPython中,如果是引用周期的一部分,则不会调用
\uuu del\uuu
方法-我不知道这是否会影响文件(我认为它们在解释器关闭时仍然关闭),但这可能会影响我们自己的对象。谢谢,响应非常好@delnan:显然,即使Python放弃了文件句柄,任何现代操作系统都会在进程关闭时关闭它。所以,对于处于读取模式的文件,谁会在乎它们是否已关闭,对吗?但是对于处于写模式的文件,情况就不同了,因为除非解释器显式关闭文件,否则文件可能不会被刷新。有关详细信息,请参见POSIX。(不知道Windows的等价物在哪里被记录。)谁投了反对票,请解释一下原因?