27

If I do the following, does filehandle get closed automatically as it goes out of scope in Python:

def read_contents(file_path):
  return file(file_path).read()

If it doesn't, how can I write this function to close the scope automatically?

bodacydo
  • 75,521
  • 93
  • 229
  • 319

2 Answers2

42

To expand on FogleBird's answer, if you do not explicitly close it then the file will be closed automatically when the file object is destroyed. In CPython this will happen as soon as there are no more references to it, e.g. if it is a local variable in a function and the function ends. However if an exception is thrown in the function and file is not explicitly closed using a with statement or a try:...finally: then a reference to the file will be kept as part of the stack trace in the traceback object and the file will not be closed, at least until the next exception is thrown.

Also IronPython and Jython use the garbage collection facilities of the .Net CLR and Java JVM respectively. These are not reference counted, so the file will remain open indefinitely until the garbage collector decides to reclaim the object's memory or the program terminates.

So in general it is important to explicitly close the file using either with: or try:...finally:.

Of course all this is holds true for any other type of object that requires explicit cleanup.

Dave Kirby
  • 25,806
  • 5
  • 67
  • 84
  • 1
    "didn't bother" - i didn't know any of this. :( – bodacydo Mar 08 '10 at 22:30
  • 2
    Also note: In Python 3, the clause "the file will not be closed, at least until the next exception is thrown" is no longer accurate; in Python 3, raising a new exception implicitly chains the exception context, so if you catch one exception and raise a new one, the traceback of the original exception is preserved in the new exception (unless they explicitly disabled context, e.g. with raising `from None`). In both Py 2 & 3 it's rather easy to create cyclic garbage via tracebacks; even when the exception is no longer referenced, you'd end up waiting for cyclic GC to cleaned, much like Jython. – ShadowRanger Aug 27 '18 at 19:54
21

It should close the file handle in the file's __del__ statement, but a better approach would be to use a with block:

def read_contents(file_path):
  with open(file_path, 'r') as f:
    return f.read()

See http://docs.python.org/library/stdtypes.html#file.close for more information.

FogleBird
  • 74,300
  • 25
  • 125
  • 131
  • Just to mention: file returns a file object which has a close method. That would be the most straight forward solution, but "with" is obviously the nicer one. – Achim Mar 08 '10 at 20:26
  • I have a problem -- I don't have `with` in my Python. Is it ok to import from future? I have Python 2.5. – bodacydo Mar 08 '10 at 20:29
  • If you have Python 2.5, then yes. – Tim Pietzcker Mar 08 '10 at 20:30
  • Thanks. One more question - if I transfer my app to installation with Python 2.6, will `import with from future` still work? – bodacydo Mar 08 '10 at 20:31
  • That or use the try/finally approach as described in the link. – FogleBird Mar 08 '10 at 20:31
  • Why is it better to use a `with` block? – HelloGoodbye Aug 14 '19 at 21:52
  • What would happen if this returned `f` itself? Would that file handle continue to be open and usable until all references to it are lost? Or does the move out of the `with` scope automatically close the handle, returning a (probably useless) closed handle to the caller? – davidA Jan 14 '22 at 00:44