File Handling

Almost every real program needs to read data from somewhere or save data somewhere permanent. Python's built-in open() function is the doorway to working with files on disk — reading their contents, writing new content, and appending to what's already there.

Opening a File with open()

The open() function takes a filename and a mode string that tells Python what you intend to do with the file:

file = open("notes.txt", "r")
ModeMeaning
'r'Read (default). The file must already exist.
'w'Write. Creates the file if it doesn't exist, and overwrites the entire content if it does.
'a'Append. Creates the file if it doesn't exist, and adds new content to the end without erasing existing content.
'r+'Read and write. The file must already exist.

Note: Opening a file in 'w' mode instantly wipes out any existing content the moment the file is opened, even before you write anything new. Double-check the mode before running write code on a file you care about.

Reading a File's Full Contents

The .read() method reads the entire file into a single string.

file = open("notes.txt", "r")
content = file.read()
print(content)
file.close()

Reading Line by Line

For larger files, it's often more memory-efficient to process one line at a time instead of loading everything at once. A file object is directly iterable in a for loop:

file = open("notes.txt", "r")
for line in file:
    print(line.strip())   # .strip() removes the trailing newline
file.close()

Writing to a File

The .write() method writes a string to the file. Combine it with mode 'w' to create/overwrite a file, or 'a' to append.

file = open("notes.txt", "w")
file.write("First line of the file.\n")
file.write("Second line of the file.\n")
file.close()

Why with open(...) as f: Is Strongly Preferred

Calling .close() manually is easy to forget, and if an error happens between open() and .close(), the file can be left open indefinitely, leaking a resource and sometimes leaving writes unflushed. Python's with statement solves this by acting as a context manager: it automatically closes the file for you as soon as the block ends — even if an exception is raised inside it. This is one of the most important idioms in everyday Python code.

with open("notes.txt", "r") as f:
    content = f.read()
    print(content)
# f is automatically closed here, even if .read() had raised an error

Worked Example: Reading and Writing Together

Here is a small program that reads an existing file, transforms its content, and then writes the result to a new file, all using the with pattern:

# read the original file
with open("notes.txt", "r") as f:
    lines = f.readlines()

# uppercase every line
uppercased = [line.upper() for line in lines]

# write the transformed lines to a new file
with open("notes_upper.txt", "w") as f:
    f.writelines(uppercased)

print("Done! Check notes_upper.txt")
Next steps: Head to Exception Handling to learn how to gracefully handle errors like a missing file.