Traditional Python teaching says that if you want to loop over the lines of a file, you should open it in a context manager like:
with open(filename) as f:
for line in f:
do_something_with(line)
Recently, I heard someone make an argument for doing the same thing with the following paradigm:
for line in open(filename):
do_something_with(line)
In CPython, I believe that the file object created by open(filename)
will be disposed of after no references to it remain. That should happen once the for
loop stops executing (i.e., it naturally finishes, an error occurs, it encounters a break
statement, etc.).
Indeed, on my machine, running the following code
import weakref
def wrap_file_io(obj):
global w
w = weakref.ref(obj, lambda c: print("The file object has been disposed of."))
return obj
def read_file():
print('Reading file...')
for line in wrap_file_io(open('file.txt')):
print(line.strip())
print('Doing some other expensive operation...')
for i in range(1000):
for j in range(1000):
i ** j
print("Expensive operation complete.")
if __name__ == '__main__':
read_file()
produces the output
Reading file...
These are the contents
of file.txt.
There are three lines.
The file object has been disposed of.
Doing some other expensive operation...
Expensive operation complete.
Which indicates that the file is cleared away before the expensive operation.
Opening a file like this makes me kind of nervous, but given the strength of CPython's object deallocation implementation, are there problems with opening a file with for line in open(filename)
? Can you provide a specific piece of code that might be problematic without the context manager?