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")
| Mode | Meaning |
|---|---|
'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")