Reading and writing files in Python

To interact with files in python, you must open the file and assign it to a variable. This variable is called a file handle. We can't directly interact with a file handle - instead, we must use the .read() method to interact with the file contents. After you've completed all operations on the file you want to do, the file handle must be closed.

Handles are defined (and thus files opened) with the open() function. This function takes two arguments:

  1. the name of the file to open
  2. the mode in which the file should be read. Modes, with usage examples, include,

    • read-only ("r"). Use this mode to read a file, but not write anything to it.

      • Usage: handle = open("filename.txt", "r")
    • write-only ("w"). Use this mode to write to an empty file.

      • Usage: handle = open("filename.txt", "w")
    • append ("a"). Use this mode to add content to an existing file.

      • Usage: handle = open("filename.txt", "a")

Opening files for reading

There are two basic ways to open and close files, shown below. Note that following two chunks of code are equivalent!

In [5]:
# For convenience, save the name of the file we want to open to a variable
filename = "important_file_for_opening.txt"

# Open and close with open() and close()
file_handle = open(filename, "r") # Open as read-only
file_contents = file_handle.read() # Read contents of file. The file_contents variable is a string that holds the file contents
file_handle.close() # Close file when finished (important!!)



# Open with open(), using the *with* control flow construct
# The file automatically closes outside the scope of the with - you can only interact with the file inside the with!
with open(filename, "r") as file_handle:
    file_contents = file_handle.read() # Again, the file_contents variable is a string that holds the file contents

# Print out the contents of the file
print file_contents
This is line 1 of the file.
This is line 2 of the file.
See? This file has 3 lines!

You'll notice that the .read() method saved the entire body of a file to a single string. Another convenient way to read a file is to save each line as a list, so that we can easily loop over the file contents. We can do this in two ways: by using the .readlines() method instead of .read(), or by converting .read() to a list using the python function split.

In [12]:
# Use the .readlines() method to save file lines to a list
with open(filename, "r") as file_handle:
    file_contents = file_handle.readlines()
    
print file_contents
print type(file_contents)
print len(file_contents)
['This is line 1 of the file.\n', 'This is line 2 of the file.\n', 'See? This file has 3 lines!']
<type 'list'>
3

Above, we see that .readlines() gave us a list with three entries, and each entry was a line in the file. You'll also notice that the first two entries of this list end with the symbol "\n". This symbols is a new-line character, and corresponds the "hidden" character in your computer when you hit enter/return. (NOTE: on PCs, this character is often represented by \r instead of \n!)

So, we since know that all lines must end with a return, we can also separate lines in the file into a list using .split():

In [14]:
# Read in file with .read()
with open(filename, "r") as file_handle:
    file_contents = file_handle.read()

# Split the string saved in file_contents on the new-line character
file_contents_list = file_contents.split("\n")
print file_contents_list
['This is line 1 of the file.', 'This is line 2 of the file.', 'See? This file has 3 lines!']

Now that we have the file lines in a list, we can easily loop over them, and perform some calculations as needed:

In [20]:
# Loop over each line in file, and use a counter to keep track of lines
counter = 1
for line in file_contents_list:
    print "Line", counter, ": ", line
    print # prints a blank line
    counter += 1
Line 1 :  This is line 1 of the file.

Line 2 :  This is line 2 of the file.

Line 3 :  See? This file has 3 lines!



Opening files for writing

Opening a file in write-mode will overwrite the file, but opening in append-mode will add to the bottom of an existing file. Note that if you open a file for writing (or appending), that file doesn't need to exist already, and a new file will be created with the specified name. Alternatively, if you attempt to open a file that does not exist for reading, you'll receive an error message.

To write to a file, you still need to open a handle, but now instead of using the .read() or .readlines() method, you will use the .write() method:

In [9]:
# Open a file for writing, and write to it
file_handle = open("file_to_fill.txt", "w") # Open file for writing
file_handle.write("I'm writing a sentence to this file!")
file_handle.close()

# Use the *with* construct to open a file for writing
with open("file_to_fill.txt", "w") as file_handle:
    file_handle.write("I'm writing a sentence to this file!")

# Verify that we wrote to the file correctly by opening and reading it
with open("file_to_fill.txt", "r") as file_handle: #note the "r" mode!
    contents = file_handle.read()
print contents
I'm writing a sentence to this file!

You'll notice that "I'm writing a sentence to this file!" has only been outputted here once, even though we wrote to the file two times in the code chunk above. This is because write-only ("w") mode will overwrite file contents - if you open a file for writing and that file already existed with content in it, that content is now gone and replaced with what you've written!

To add new contents to an existing file without overwriting the contents, open the file in append ("a") mode. Anything you write here will now be added to the bottom of the file:

In [10]:
# Open a file for appending, and append text to it
file_handle = open("file_to_fill.txt", "a")
file_handle.write("\nI'm writing another line to this existing file!") # the \n means "new-line" character (basically, pressing enter/return)
file_handle.close()

# Verify that we appended to the file correctly by opening and reading it
with open("file_to_fill.txt", "r") as file_handle:
    contents = file_handle.read()
print contents
I'm writing a sentence to this file!
I'm writing another line to this existing file!