| layout | default |
|---|---|
| title | File Handling |
| parent | Lessons |
| nav_order | 11 |
| permalink | /lessons/file-handling/ |
| course_lesson | true |
| course_index | 11 |
| previous_page | /lessons/functions/ |
| previous_title | Functions |
| next_page | /lessons/exception-handling/ |
| next_title | Exception Handling |
Variables disappear when a program ends. Files let a program store information for the next run.
A variable is like writing on a classroom whiteboard: it is cleared when the program finishes. A file is like writing in a notebook that can be opened again tomorrow.
program -> write -> file on storage -> read during a later run
file = open("notes.txt", "r", encoding="utf-8")
content = file.read()
file.close()The encoding makes text handling explicit. Calling close() matters, but the safer approach is with.
with open("notes.txt", "w", encoding="utf-8") as file:
file.write("Learn Python\n")The file closes automatically when the block ends, even when an error occurs.
Important fact: prefer
with open(...)because it closes the file automatically. A file that remains open may keep operating-system resources busy and may not finish writing buffered data when expected.
| Mode | Meaning |
|---|---|
"r" |
read; file must exist |
"w" |
write; replaces existing content |
"a" |
append at the end |
"x" |
create; fails if file exists |
Be careful with "w": it can erase existing content.
with open("notes.txt", encoding="utf-8") as file:
all_text = file.read()
with open("notes.txt", encoding="utf-8") as file:
first_line = file.readline()
with open("notes.txt", encoding="utf-8") as file:
for line in file:
print(line.rstrip())rstrip() removes the line ending for display. Avoid calling .read() on a huge file when line-by-line processing is enough.
open("notes.txt") looks relative to the program's current working directory, not necessarily the folder containing the .py file. Print the current directory while debugging:
The current working directory is the folder from which Python was started. A path tells Python where a file or folder is located.
from pathlib import Path
print(Path.cwd())from pathlib import Path borrows the Path tool from Python's standard library. Imports receive a complete explanation in Chapter 13; for now, type the line exactly as shown.
pathlib.Path is a modern way to work with paths:
from pathlib import Path
path = Path("data") / "notes.txt"
path.parent.mkdir(exist_ok=True)
path.write_text("Hello\n", encoding="utf-8")CSV stores rows and columns. Use the csv module instead of manually splitting commas when data may contain commas:
CSV means comma-separated values. A CSV-aware tool understands quoted values that themselves contain commas.
import csv
with open("students.csv", newline="", encoding="utf-8") as file:
for row in csv.DictReader(file):
print(row["name"], row["marks"])JSON represents dictionaries, lists, strings, numbers, booleans, and null values:
JSON means JavaScript Object Notation. It is a text format shared by many programming languages. JSON null becomes Python None when loaded.
import json
students = [{"name": "Meera", "marks": 86}]
with open("students.json", "w", encoding="utf-8") as file:
json.dump(students, file, indent=2)
with open("students.json", encoding="utf-8") as file:
loaded_students = json.load(file)with open("expenses.txt", "a", encoding="utf-8") as file:
file.write("food,250\n")
total = 0
with open("expenses.txt", encoding="utf-8") as file:
for line in file:
category, amount = line.strip().split(",")
total += float(amount)
print(f"Total: {total:.2f}")- Using write mode when append mode was intended.
- Forgetting
encoding="utf-8"for text files. - Assuming a relative path starts beside the script.
- Forgetting to handle a missing file.
- Storing comma-containing data by manually splitting CSV lines.
with open("notes.txt", "w", encoding="utf-8") as file:
file.write("One more note\n")The learner wanted to keep old notes and add a new one.
file = open("notes.txt", encoding="utf-8")
file.close()
content = file.read()with open("data/marks.txt", encoding="utf-8") as file:
print(file.read())The code fails when the data folder does not exist in the current working directory.
Show Bug Hunter fixes
# Bug 1: append instead of replacing.
with open("notes.txt", "a", encoding="utf-8") as file:
file.write("One more note\n")
# Bug 2: read inside a with block.
with open("notes.txt", encoding="utf-8") as file:
content = file.read()
# Bug 3: confirm the current folder and create the expected data folder/file.
from pathlib import Path
print(Path.cwd())Optional deeper look: what does a Python file wrap?
The operating system gives Python a small identifier for an open file, called a file descriptor. Python adds buffering and, for text files, encoding and decoding. Buffering groups many small reads or writes for efficiency. Closing or leaving a with block releases these layers safely.
Try these problems on this page. Before coding, decide what the file should contain and which mode you need.
- Write three lines to a text file.
- Read and print a file line by line.
- Count lines and words in a file.
- Append a new expense to a file.
- Copy one file into another file.
- Read a CSV-style file and calculate a total column.
- Save a list of students as JSON.
- Load JSON and display students above a mark threshold.
- Build a file-based notes application.
- Build an expense tracker that saves data and calculates a total.
Show hints
- Use write mode and include a newline after each line.
- Iterate over the file object.
- Use
splitlines()andsplit(). - Use append mode so old expenses remain.
- Read the source, then write the destination.
- Split each row and convert the number column.
- Use the
jsonmodule andjson.dump(). - Load the JSON into Python objects, then filter them.
- Decide commands such as add, list, and exit.
- Choose one record format and use it consistently.
Show solution ideas
with open(path, "w", encoding="utf-8") as file: file.write(text).- Use
for line in fileandline.rstrip(). - Read the text and count
splitlines()andsplit(). - Open with mode
"a"and write one record followed by\n. - Use a read block and a separate write block.
- Parse the header, then add the numeric field from each row.
json.dump(students, file, indent=2).students = json.load(file)followed by a loop or filter.- Keep file operations in small functions.
- Store each expense with a category and amount, then read and add amounts.
Create a journal program that appends dated entries to a file and provides a command to display all previous entries.
Write a program that appends one expense per line and reads the file to calculate the total.