In this article, we will discuss how to use “open with” statement to open a file and what are its benefits. Also, how to open multiple files in a single “open with” statement.

The need for “open with” statement

Before going into the “with statement” we need to understand the requirement behind it. For that, we first need to know how to open a file in python.

In python to read or write a file, we need first to open it and python provides a function open(), which returns a file object. Using this file object, we can read and write in the file. But in the end, we need to close the file using this same.

Check out this example,

# open a file
file_object = open('sample.txt')

# read the file content
data = file_object.read()

# print file content
print(data)

#close the file
file_object.close()

This example assumes that we have a file sample.txt in the current folder and print its contents i.e.
This is a sample file.
It contains some sample string.
you are going to use it.
Thanks.

If you don’t have sample.txt in the current directory then you might get an error like this,
FileNotFoundError: [Errno 2] No such file or directory: 'sample.txt'

So, to avoid above error in all the examples of this article, we suggest to create a file sample.txt with some dummy text in the current folder from where you are executing this python code.

In the above example, we opened a file sample.txt using open() function, which returned a file object. Then read file’s content as string using file object’s read() function. Then printed that and in the end closed this file using the same file object.

This will work fine in typical scenarios, but there can be problems in some situations like,

What if someone forgets to close the file in the end?

Well, it seems highly impossible now, but in big projects, people usually do big stuff after opening files, and it includes many conditions and checks. So, there can be scenarios when the return statement hit before close() function gets called, or it got skipped sue to some if condition in code.

Well, in scenarios like these, till we don’t call the close() function, the file will remain open, and its object will be consuming the memory of our process. Also, there might be chances that data will not entirely be flushed to the file. Closing a file using close() function is a graceful way of closing the file.

What if an exception comes?

Check out this code

# File is not closed in case of exception
try:
    # open a file
    file_object = open('sample.txt')
    # read file content
    data = file_object.read()
    # It will raise an exception
    x = 1 / 0
    print(data)
    file_object.close()
except:
    # Handling the exception
    print('An Error')
finally:
    if file_object.closed == False:
        print('File is not closed')
    else:
        print('File is closed')

Output:
An Error
File is not closed

In this code, we are closing the file properly by calling close() function and catching the exception too. But a closure look will show you that when the exception occurred, control moved to the except block and then to the finally block. In the finally block, we check if the file is closed or not. Guess what! file was not closed because due to exception, call to close() function got skipped. To fix this, we need to call the close() function in except block like this,
# File is not closed in case of exception
try:
    # open a file
    file_object = open('sample.txt')
    # read file content
    data = file_object.read()
    # It will raise an exception
    x = 1 / 0
    print(data)
    file_object.close()
except:
    file_object.close()
    # Handling the exception
    print('An Error')
finally:
    if file_object.closed == False:
        print('File is not closed')
    else:
        print('File is closed')

As you can see the close() function is called two times here to avoid the bug. When code gets bigger, then there are high chances of skipping the close() somewhere. So, to avoid these kinds of problems, we should always open a file using “open with” statement in python. Let’s see how to do that

How to open a file using “open with” statement in python

# using "with statement" with open() function
with open('sample.txt', "r") as file_object:
    # read file content
    data = file_object.read()
    # print file contents
    print(data)

# Check if file is closed
if file_object.closed == False:
    print('File is not closed')
else:
    print('File is closed')

Output:
This is a sample file.
It contains some sample string.
you are going to use it.
Thanks.
File is closed

“with statement” creates an execution block and object created in the with statement will be destroyed or gracefully closed when this execution block ends.

It means when we used “with statement” with open() function, an execution blocked started and the file object returned by open() function is assigned to file_object. When this execution block of “with statement” end, then the file object’s close function gets called automatically, and the file will be closed gracefully. We don’t need to manually call the close() function anymore if we are using “with statement”

Benefits of calling open() using “with statement”

Fewer chances of bug due to coding error

No need to explicitly close the opened file, “with statement” takes care of that. When with the block ends, it will automatically close the file. So, it reduces the number of lines of code and reduces the chances of bug.

Excellent handling in case of exception

Check out this example,

# File will be closed before handling the exception
try:
    # using "with statement" with open() function
    with open('sample.txt', "r") as file_object:
        # read file content
        data = file_object.read()
        # it raises an error
        x = 1 / 0
        print(data)
except:
    # handling exception
    print('An Error')
    if file_object.closed == False:
        print('File is not closed')
    else:
        print('File is closed')

Output:
An Error
File is closed

If we have opened a file using “with statement” and an exception comes inside the execution block of “with statement”. Then file will be closed before control moves to the except block.

We don’t need to call the close() function even in case of exceptions, execution block of “with statement” handles that too and closes the file before exception handling.

We confirmed this using file_object.closed in the except block.

Open multiple files in a single “with statement”

Let’s open two files using a single “with statement”. We will read from sample.txt and write in the outfile.txt,

# Read from sample.txt and write in outfile.txt
with open('outfile.txt', 'w') as file_obj_2, open('sample.txt', 'r') as file_obj_1:
    data = file_obj_1.read()
    file_obj_2.write(data)
    # Both the files will be closed automatically when execution block ends.

As we are using the “with statement”, so when execution block ends, close() function will be called on both the file objects automatically.

The complete example is as follows,

def main():

    print('*** Open a file using without "open with" statement ***')

    print('Normal way of opening & reading from a file using open() function')

    # open a file
    file_object = open('sample.txt')

    # read the file content
    data = file_object.read()
    print(data)

    #close the file
    file_object.close()

    print('** Open a file using open() function & handle exception **')

    # File is not closed in case of exception
    try:
        # open a file
        file_object = open('sample.txt')
        # read file content
        data = file_object.read()
        # It will raise an exception
        x = 1 / 0
        print(data)
        file_object.close()
    except:
        # Handling the exception
        print('An Error')
    finally:
        if file_object.closed == False:
            print('File is not closed')
        else:
            print('File is closed')

    print('**** Open a file using "open with" statement ****')

    # using "with statement" with open() function
    with open('sample.txt', "r") as file_object:
        # read file content
        data = file_object.read()
        # print file contents
        print(data)

    # Check if file is closed
    if file_object.closed == False:
        print('File is not closed')
    else:
        print('File is closed')

    print('**** "open with" statement & Exception handling ****')

    # File will be closed before handling the exception
    try:
        # using "with statement" with open() function
        with open('sample.txt', "r") as file_object:
            # read file content
            data = file_object.read()
            # it raises an error
            x = 1 / 0
            print(data)
    except:
        # handling exception
        print('An Error')
        if file_object.closed == False:
            print('File is not closed')
        else:
            print('File is closed')


    print('**** Multiple open() function calls in a single "with statement" ****')

    # Read from sample.txt and write in outfile.txt
    with open('outfile.txt', 'w') as file_obj_2, open('sample.txt', 'r') as file_obj_1:
        data = file_obj_1.read()
        file_obj_2.write(data)
        # Both the files will be closed automatically when execution block ends.

if __name__ == '__main__':
   main()

Output:
*** Open a file using without "open with" statement ***
Normal way of opening & reading from a file using open() function
This is a sample file.
It contains some sample string.
you are going to use it.
Thanks.
** Open a file using open() function & handle exception **
An Error
File is not closed
**** Open a file using "open with" statement ****
This is a sample file.
It contains some sample string.
you are going to use it.
Thanks.
File is closed
**** "open with" statement & Exception handling ****
An Error
File is closed
**** Multiple open() function calls in a single "with statement" ****

Join a list of 2000+ Programmers for latest Tips & Tutorials