Will file be closed automatically in a "for ... in open..." statement?
Cameron Simpson
cs at zip.com.au
Tue Feb 16 04:24:05 EST 2016
On 16Feb2016 00:39, jfong at ms4.hinet.net <jfong at ms4.hinet.net> wrote:
>I know
>
> with open('foo.txt') as f:
> ...do something...
>
>will close the file automatically when the "with" block ends.
Yes, because open is a context manager - they're great for reliably tidying up
in the face of exceptions or "direct" departure from the block, such as a
"return" statement.
>I also saw codes in a book:
>
> for line in open('foo.txt'):
> ...do something...
>
>but it didn't mention if the file will be closed automatically or not when the
>"for" block ends. Is there any document talking about this? and how to know if
>a file is in "open" or not?
This does not reliably close the file.
In CPython (the common implementation, and likely what you are using), objects
are reference counted and when the interpreter notices their counter go to
zero, the object's __del__ method is called before releasing the object's
memory.
For an open file, __del__ _does_ call close if the file is open. However, only
reference counting Pythons will call __del__ promptly - other systems rely on
garbage collectors to detect unused objects.
In the for loop above, for interpreter obtains an iterator from the open file
which returns lines of text. That iterator has a reference to the open file,
and the for loop has a reference to the iterator. Therefore the file remains
references while the loop runs. AT the end of the loop the iterator is
discarded, reducing its references to zero. That in turn triggers releasing the
open file, dropping its references to zero.
In CPython, that in turn will fire the open file's __del__, which will close
the file. In other Pythons, not necessarily that promptly.
Also, there are plenty of ways to phrase this where the file reference doesn't
go to zero. FOr example:
f = open(...)
for line in f:
...
You can see that it is easy to forget to close the file here (especially if you
have an exception or exit the function precipitously).
Try to use the "with open(...) as f:" formulation when possible. It is much
better.
Cheers,
Cameron Simpson <cs at zip.com.au>
More information about the Python-list
mailing list