Reading & Writing Files
Learn how to open, read, write, and safely close files in Python using the recommended `with` block.
Programs that only work in memory forget everything the moment they stop running. Files let your program remember things — save a score, store a to-do list, or process a data set. In this lesson you will learn how Python opens files, reads their contents, and writes new content back — all without losing data by accident.
See it in action
— step through the idea, then dive into the details below.Files: Memory That Survives
Variables vanish the moment a program stops. Files let your Python program save data to disk — and read it back anytime.
#Opening a File with open()
Python's built-in open() function is the key that unlocks any file. You give it two things: - The path to the file (e.g. "notes.txt") - The mode — what you intend to do with the file
The most common modes are: - "r" — read an existing file (default) - "w" — write a new file (overwrites if it already exists!) - "a" — append to the end of an existing file without erasing it
Think of a file like a notebook
Opening in "r" mode is like picking up a notebook to read it. Opening in "w" mode is like tearing out all the pages and starting fresh. Opening in "a" mode is like flipping to the last blank page and continuing where you left off.
#Why Closing Files Matters
When Python opens a file, the operating system reserves a small resource called a file handle. If you forget to close the file, that handle leaks — your program holds the file open longer than needed, which can prevent other programs (or even your own code) from accessing it, and data you wrote may not be fully saved to disk.
The old way required remembering to call f.close() by hand. It is easy to forget, especially when errors happen.
# Old style — you must remember to close manually
f = open("notes.txt", "r")
content = f.read()
f.close() # easy to forget!
print(content)#The Right Way: with open(...) as f:
Python has a much safer pattern called a context manager. When you use with open(...) as f:, Python automatically closes the file the moment the indented block finishes — even if an error crashes your code halfway through. You never have to remember f.close().
# Recommended style — file closes automatically
with open("notes.txt", "r", encoding="utf-8") as f:
content = f.read()
# File is already closed here, safely
print(content)Always pass encoding="utf-8"
Different computers use different default text encodings. Specifying encoding="utf-8" makes your code behave the same on every machine and handles accented characters, emoji, and non-English text correctly.
#Reading Files
Once a file is open in "r" mode, you have several ways to read its contents:
# read() — loads the entire file as one big string
with open("poem.txt", "r", encoding="utf-8") as f:
all_text = f.read()
print(all_text)# readline() — reads one line at a time
with open("poem.txt", "r", encoding="utf-8") as f:
first_line = f.readline()
second_line = f.readline()
print(first_line)
print(second_line)# readlines() — returns a list, one string per line
with open("poem.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
print(lines)# Iterating directly — the most memory-efficient approach
with open("poem.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip()) # strip() removes the trailing newline#Writing Files
Open with "w" mode and call write() to save text. Remember: "w" erases the file first if it already exists.
# Write mode — creates the file (or overwrites it)
with open("greeting.txt", "w", encoding="utf-8") as f:
f.write("Hello, world!\n")
f.write("This file was created by Python.\n")
print("File written!")"w" mode silently erases existing content
If greeting.txt already had text in it, opening with "w" destroys that text immediately — before you write a single byte. If you want to add to an existing file, use "a" (append) mode instead.
#Appending to a File
# Append mode — adds to the end without erasing
with open("log.txt", "a", encoding="utf-8") as f:
f.write("User logged in at 09:00\n")
# Run again and it adds another line instead of replacing
with open("log.txt", "a", encoding="utf-8") as f:
f.write("User logged out at 10:30\n")
with open("log.txt", "r", encoding="utf-8") as f:
print(f.read())write() only accepts strings
Unlike print(), the write() method does not accept numbers or lists directly. You must convert them first: ``python f.write(str(42) + "\n") # correct f.write(42) # TypeError! ``
You want to add a new line to the end of an existing file without deleting its current contents. Which mode should you use?
Key takeaways
- Use `open(path, mode, encoding="utf-8")` to open files; mode is `"r"`, `"w"`, or `"a"`.
- Always use `with open(...) as f:` — it closes the file automatically, even if an error occurs.
- `read()` loads everything, `readline()` loads one line, and looping over `f` is the most memory-efficient option.
- `write()` saves text but does NOT add a newline — you must include `\n` yourself.
- `"w"` mode erases existing content; use `"a"` to safely append without destroying old data.
What does this code print?
with open("demo.txt", "w", encoding="utf-8") as f:
f.write("Hello")
f.write(" World")
with open("demo.txt", "r", encoding="utf-8") as f:
print(f.read())This code is supposed to save a score to a file, but it crashes. What is wrong?
score = 42
with open("score.txt", "w", encoding="utf-8") as f:
f.write(score)Complete the code so it opens 'notes.txt' in append mode and adds a new line to the end without erasing existing content.
with open("notes.txt", , encoding="utf-8") as f: f.write("New note\n")
Put these lines in the right order to write a file, then read it back and print each line without extra blank lines.
with open("msg.txt", "r", encoding="utf-8") as f:with open("msg.txt", "w", encoding="utf-8") as f: f.write("Hello\nWorld\n")print(line.strip())
for line in f:
Create a program that does three things in order: 1. Writes a shopping list (at least three items, one per line) to a file called shopping.txt. 2. Appends one more item to the same file. 3. Reads the file back and prints each line with its line number (e.g. 1: Apples).
Try it live — edit the code and hit Run to execute real Python: