You never have to close File s, because it is basically a representation of a path. Only Streams and Readers/Writers. In fact, File does not even have a close() method.
If you write to a file without closing, the data won't make it to the target file. But after some surfing I got to know that Python automatically closes a file when the reference object of a file is reassigned to another file. It is a good practice to use the close() method to close a file.
You've learned why it's important to close files in Python. Because files are limited resources managed by the operating system, making sure files are closed after use will protect against hard-to-debug issues like running out of file handles or experiencing corrupted data.
In general, you should always close a file after you are done using it.
The pythonic way to deal with this is to use the with
context manager:
with open(from_file) as in_file, open(to_file, 'w') as out_file:
indata = in_file.read()
out_file.write(indata)
Used with files like this, with
will ensure all the necessary cleanup is done for you, even if read()
or write()
throw errors.
You asked about the "basic concepts", so let's take it from the top: When you open a file, your program gains access to a system resource, that is, to something outside the program's own memory space. This is basically a bit of magic provided by the operating system (a system call, in Unix terminology). Hidden inside the file object is a reference to a "file descriptor", the actual OS resource associated with the open file. Closing the file tells the system to release this resource.
As an OS resource, the number of files a process can keep open is limited: Long ago the per-process limit was about 20 on Unix. Right now my OS X box imposes a limit of 256 open files (though this is an imposed limit, and can be raised). Other systems might set limits of a few thousand, or in the tens of thousands (per user, not per process in this case). When your program ends, all resources are automatically released. So if your program opens a few files, does something with them and exits, you can be sloppy and you'll never know the difference. But if your program will be opening thousands of files, you'll do well to release open files to avoid exceeding OS limits.
There's another benefit to closing files before your process exits: If you opened a file for writing, closing it will first "flush its output buffer". This means that i/o libraries optimize disk use by collecting ("buffering") what you write out, and saving it to disk in batches. If you write text to a file and immediately try to reopen and read it without first closing the output handle, you'll find that not everything has been written out. Also, if your program is closed too abruptly (with a signal, or occasionally even through normal exit), the output might never be flushed.
There's already plenty of other answers on how to release files, so here's just a brief list of the approaches:
Explicitly with close()
. (Note for python newbies: Don't forget the parens! My students like to write in_file.close
, which does nothing.)
Recommended: Implicitly, by opening files with the with
statement. The close()
method will be called when the end of the with
block is reached, even in the event of abnormal termination (from an exception).
with open("data.txt") as in_file:
data = in_file.read()
Implicitly by the reference manager or garbage collector, if your python engine implements it. This is not recommended since it's not entirely portable; see the other answers for details. That's why the with
statement was added to python.
Implicitly, when your program ends. If a file is open for output, this may run a risk of the program exiting before everything has been flushed to disk.
The default python interpeter, CPython, uses reference counting. This means that once there are no references to an object, it gets garbage collected, i.e. cleaned up.
In your case, doing
open(to_file, 'w').write(indata)
will create a file object for to_file
, but not asign it to a name - this means there is no reference to it. You cannot possibly manipulate the object after this line.
CPython will detect this, and clean up the object after it has been used. In the case of a file, this means closing it automatically. In principle, this is fine, and your program won't leak memory.
The "problem" is this mechanism is an implementation detail of the CPython interpreter. The language standard explicitly gives no guarantee for it! If you are using an alternate interpreter such as pypy, automatic closing of files may be delayed indefinitely. This includes other implicit actions such as flushing writes on close.
This problem also applies to other resources, e.g. network sockets. It is good practice to always explicitly handle such external resources. Since python 2.6, the with
statement makes this elegant:
with open(to_file, 'w') as out_file:
out_file.write(in_data)
TLDR: It works, but please don't do it.
It is good practice to use the with
keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way. It is also much shorter than writing equivalent try-finally blocks:
>>> with open('workfile', 'r') as f:
... read_data = f.read()
>>> f.closed
True
The answers so far are absolutely correct when working in python. You should use the with open()
context manager. It's a great built-in feature, and helps shortcut a common programming task (opening and closing a file).
However, since you are a beginner and won't have access to context managers and automated reference counting for the entirety of your career, I'll address the question from a general programming stance.
The first version of your code is perfectly fine. You open a file, save the reference, read from the file, then close it. This is how a lot of code is written when the language doesn't provide a shortcut for the task. The only thing I would improve is to move close()
to where you are opening and reading the file. Once you open and read the file, you have the contents in memory and no longer need the file to be open.
in_file = open(from_file)
indata = in_file.read()
out_file.close()
out_file = open(to_file, 'w')
out_file.write(indata)
in_file.close()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With