Does a File Object Automatically Close when its Reference Count Hits Zero?

The answer is in the link you provided.

Garbage collector will close file when it destroys file object, but:

  • you don't really have control over when it happens.

    While CPython uses reference counting to deterministically release resources (so you can predict when object will be destroyed) other versions don't have to. For example both Jython or IronPython use JVM and .NET garbage collector which release (and finalize) objects only when there is need to recover memory and might not do that for some object until the end of the program. And even for CPython GC algorithm may change in the future as reference counting isn't very efficient.

  • if exception is thrown when closing file on file object destruction, you can't really do anything about it because you won't know.


If you want to be sure, I'd write the code like this:

from __future__ import with_statement

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

That way, your file closes as expected, even with exceptions.


Much later: here is some code with import dis to show how the compiler treats these differently.

>>> 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 

For the cpython implementation of python: yes, it is guaranteed to be closed when its reference count goes to zero.

For python as an abstract language (e.g., including Jython, IronPython, etc): no, it is not guaranteed to be closed. In particular, an implementation of Python may choose not to use reference counting, but to use some other form of GC.

References:

  • http://docs.python.org/c-api/typeobj.html#tp_dealloc
  • http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/

No, Python optimize deleting unused objects so It may never close your file (OK at the end of your script at exit it will cleanup). @ hughdbrown have pointed out nice solution.