You are reading solutions / Python

# Python close() File – Open and Close Files Properly

For anyone working with Python, interacting with files will be unavoidable. The simplest method for opening and closing files is below.

file = open('example_file.txt')  # open the example file
file.close()                     # close it

One of the most common mistakes people make when using files in Python is not closing them afterward. In this lesson, we'll look at some issues caused by leaving files open and how we can avoid these by using the established best practice.

## Why Close Files?

Not closing a file after an interaction is not only a waste of program resources but could also prevent other file interactions and may lead to inconsistencies when running your scripts on different Python versions. Leaving files open is also widely regarded as poor practice, and it's always best to get into good habits early on.

## Example 1: Not closing correctly

Imagine you've got a file, called file_1.txt, store in the same directory as your Python script. This file contains the text "This is the file 1 text".

You want to read the file into Python, display the text, and append a new line to mark that you have read the text file. This process is shown (incorrectly) below:

file = open('file_1.txt','r')        # file is opened in read (r) mode

file = open('file_1.txt', 'a')       # file is opened in append (a) mode
file.write(' and we have read it.')

file = open('file_1.txt','r')        # file is opened in read (r) mode

file.close()
Out:
This is file 1 text
This is file 1 text and we have read it.

The file was closed correctly, right? Wrong.

In this example, we have only closed the file after the most recent open. For some Python versions, the code used might not record the appended text correctly as the file wasn't closed after completing the operation. To demonstrate this, observe what happens if we try to close each file individually at the end as a solution:

f1 = open('file_1.txt','r')

f2 = open('file_1.txt', 'a')
f2.write(' and we have read it.')

f3 = open('file_1.txt','r')

f1.close()
f2.close()
f3.close()
Out:
This is file 1 text
This is file 1 text

We can see that appending to the file from f2 isn't reflected in f3.

Coding like this could also potentially corrupt a file, preventing it from being read or used again in the future. This example is simple, but if you were writing a script that appended extra information to a long file filled with valuable customer data or data that's taken months to web scrape, file corruption would become a costly problem.

To fix this example, we would need to make sure to close the file after writing before trying to read it again:

f1 = open('file_1.txt','r')
f1.close()

f2 = open('file_1.txt', 'a')
f2.write(' and we have read it.')
f2.close()

f3 = open('file_1.txt','r')
f3.close()
Out:
This is file 1 text
This is file 1 text and we have read it.

An easier alternative to manually handling the .close() for each file is to use a context manager.

## Example 2: Context Managers

To close files property, the most straightforward solution that follows best practices is to use what's called a with statement whenever opening a file. This pattern is also known as using a context manager, a fundanmental concept in Python.

Below is an example of using a with statement to make sure files are closed:

with open('file_1.txt','r') as f:

with open('file_1.txt', 'a') as f:
f.write(' and we have read it.')

with open('file_1.txt','r') as f:
print(f.read())
Out:
This is file 1 text and we have read it.
This is file 1 text and we have read it. and we have read it.

The updated code provides the same functionality with less coding required. Using a with open() statement will automatically close a file once the block has completed.

Not only will using a context manager free you from having to remember to close files manually, but it will also make it much easier for others reading your code to see precisely how the program is using the file.

Using with open() is often the right choice, but there may be situations where your project may call for manually closing files.

### Context manager scoping errors

When using a context manager, there are a few errors that could occur. One example of this is a ValueError: I/O operation on closed file. Consider the code below:

with open('file_2.txt', 'a') as f:
message = 'This is the file 2 text'
f.write(message)
Out:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-2deecae51d65> in <module>
1 with open('file_2.txt', 'w') as f:
2     message = 'This is the file 2 text'
----> 3 f.write(message)

ValueError: I/O operation on closed file.

This error is occurs because we've used a write() file operation outside of with open() scope. Since the context manager automatically closes the file after executing the indented code, Python cannot perform any subsequent file operations. We can easily fix this problem by keeping everything under the with open() scope, like so:

with open('file_2.txt', 'a') as f:
message = 'This is the file 2 text'
f.write(message)

The new script executes successfully, writing the message to the file before closing it.

## Summary

Anyone working with Python will most likely need to work with files extensively. An essential part of file interaction is making sure to close them when you have finished!

Leaving files open can cause many problems, especially in large projects that rely on a wide range of files.

As we've discussed, a simple way to avoid the complications that leaving files open can potentially cause is to open your files using a context manager, which automatically closes files for you. Following this pattern will save you a job while preventing wasted resources and version inconsistencies. Most importantly, using with statements will help make your code look clean and professional.