3

I've come across some code that iterates through lines in a file like so:

for line in open(filename, 'r'):
    do_all_the_things()

Is that a more Pythonic version of something like:

with open(filename, 'r') as f:
    for line in f:
        do_all_the_things()

It uses less indentation levels, so it looks nicer, but is it the same? From what I know, with basically adds a finally: f.close() or something to that effect to ensure after leaving the block the object is cleaned up. When the first for loop ends (or is cut short with a break perhaps) and the variable goes out-of-scope does the same thing happen? Can I take my cue from the first bit of code and save myself some keystrokes, or rather, should I fix it?

agf
  • 171,228
  • 44
  • 289
  • 238
Nick T
  • 25,754
  • 12
  • 83
  • 121
  • possible duplicate of [Python: Is explicitly closing files important?](http://stackoverflow.com/questions/7395542/python-is-explicitly-closing-files-important) Also related to: http://stackoverflow.com/questions/575278/how-does-python-close-files-that-have-been-gced – Bakuriu Apr 19 '13 at 17:20

2 Answers2

2

You're not creating any reference to the file object other than within the iterator used by the for loop.

That means as soon as the for loop ends, that iterator, then the file object, will have their reference counts go to zero and they will be deleted.

When a file object is deleted, it is closed.

So you're not leaving open files by using the bare for loop.

That said, in a larger program, it's good to be explicit -- and the with statement says clearly that the file is used only within that context.

Personally, if I'm opening a file for writing / appending, then I'll use with even if I'm only using it in one place. If I'm just opening it for reading and not creating an explicit reference, I just use the object directly.

agf
  • 171,228
  • 44
  • 289
  • 238
  • The example in the documentation for [`file.close`](http://docs.python.org/2/library/stdtypes.html#file.close) *seems* to disagree with you. – Bakuriu Apr 19 '13 at 17:18
  • "So you're not leaving open files by using the bare `for` loop" That might be true in Cpython, but it certainly isn't guaranteed by the specification – mgilson Apr 19 '13 at 17:20
  • @mgilson I'm aware. If I wanted guarantees I'd use a compiled language with a true type system; I'm perfectly happy with "best effort" in most cases -- especially if the Python process is short-lived so you don't have to worry about leaking file handles anyway. – agf Apr 19 '13 at 17:44
  • @Bakuriu It's the difference between a guarantee and the reality of the garbage collection in each Python implementation. I describe what happens in all normal circumstances, not what is guaranteed to happen. – agf Apr 19 '13 at 17:46
1

Definitely use the context manager. It is the only way to guarantee that your file object is handled properly.

While the first version will likely not give you any problems in Cpython (currently), the specification never specifies when (or even if) __del__ is called. Because of this, you can't know for sure that your file object ever gets properly finalized using the first version.

mgilson
  • 300,191
  • 65
  • 633
  • 696