当文件对象的引用计数达到零时自动关闭?

时间:2009-12-02 17:35:40

标签: python

我的印象是文件对象在引用计数达到0时立即关闭,因此行:

foo = open('foo').read()

会获取文件的内容并立即关闭文件。但是,在阅读Is close() necessary when using iterator on a Python file object的答案后,我得到的印象是,这种情况不会发生,并且在文件对象上调用.close() 总是是必要的。

上面的那行是否按照我的想法行事,即使它确实如此,它是Pythonic要做的吗?

4 个答案:

答案 0 :(得分:30)

答案在您提供的链接中。

垃圾收集器在销毁文件对象时会关闭文件,但是:

  • 你真的无法控制它何时发生。

    虽然CPython使用引用计数来确定性地释放资源 (因此您可以预测何时销毁对象)其他版本不必。 例如,Jython或IronPython都使用JVM和.NET垃圾收集器 仅在需要恢复内存时才释放(并完成)对象 并且在程序结束之前可能不会为某个对象执行此操作。 甚至对于CPython GC算法可能在将来作为引用计数而改变 效率不高。

  • 如果在文件对象销毁时关闭文件时抛出异常, 你不能真正做任何事情,因为你不会知道。

答案 1 :(得分:27)

如果你想确定,我会编写如下代码:

from __future__ import with_statement

with open('foo') as f:
    foo = f.read()

这样,即使有例外情况,您的文件也会按预期关闭。


很久以后:这里有一些代码import dis来说明编译器如何区别对待这些代码。

>>> def foo(filename):
...     with open(filename) as f:
...         return f.read()
... 
>>> def bar(filename):
...     return open(filename).read()
... 
>>> from dis import dis
>>> 
>>> dis(foo)
  2           0 LOAD_GLOBAL              0 (open)
              3 LOAD_FAST                0 (filename)
              6 CALL_FUNCTION            1
              9 DUP_TOP             
             10 LOAD_ATTR                1 (__exit__)
             13 ROT_TWO             
             14 LOAD_ATTR                2 (__enter__)
             17 CALL_FUNCTION            0
             20 STORE_FAST               1 (_[1])
             23 SETUP_FINALLY           23 (to 49)
             26 LOAD_FAST                1 (_[1])
             29 DELETE_FAST              1 (_[1])
             32 STORE_FAST               2 (f)

  3          35 LOAD_FAST                2 (f)
             38 LOAD_ATTR                3 (read)
             41 CALL_FUNCTION            0
             44 RETURN_VALUE        
             45 POP_BLOCK           
             46 LOAD_CONST               0 (None)
        >>   49 WITH_CLEANUP        
             50 END_FINALLY         
             51 LOAD_CONST               0 (None)
             54 RETURN_VALUE        
>>> dis(bar)
  2           0 LOAD_GLOBAL              0 (open)
              3 LOAD_FAST                0 (filename)
              6 CALL_FUNCTION            1
              9 LOAD_ATTR                1 (read)
             12 CALL_FUNCTION            0
             15 RETURN_VALUE 

答案 2 :(得分:10)

对于python的cpython实现:是的,保证在引用计数为零时关闭。

对于python作为抽象语言(例如,包括Jython,IronPython等):不,不保证关闭它。特别是,Python的实现可能选择不使用引用计数,而是使用其他形式的GC。

<强>参考文献:

答案 3 :(得分:1)

不,Python优化删除未使用的对象,因此它可能永远不会关闭您的文件(在退出时脚本结束时确定它将清理)。 @ hughdbrown指出了很好的解决方案。

相关问题