Reading & Writing Files
Learn how to open, read, write, and append to files in Python using the open() function.
Reading & Writing Files
Almost every real program works with files — reading data from a CSV, writing logs, saving user settings, processing text. Python makes file handling simple and clean.
The foundation of everything is one built-in function — open().
How open() works
file = open("filename.txt", "mode")The first argument is the filename. The second is the mode — what you want to do with the file.
| Mode | Meaning |
|---|---|
"r" | Read — default mode, file must exist |
"w" | Write — creates file if not exists, overwrites if it does |
"a" | Append — adds to the end, creates file if not exists |
"x" | Create — creates new file, fails if it already exists |
"rb" | Read binary — for images, PDFs, non-text files |
"wb" | Write binary |
"r+" | Read and write |
Mode "w" deletes all existing content and starts fresh. If you want to keep the existing content and just add to it, use "a" (append) instead.
Reading a file
read() — read the entire file at once
file = open("notes.txt", "r")
content = file.read()
print(content)
file.close()read() returns the entire file as one big string. close() releases the file when you are done — important, because leaving files open wastes memory and can cause issues.
But there is a better way to handle files — the with statement:
with open("notes.txt", "r") as file:
content = file.read()
print(content)
# file is automatically closed here — no need to call close()Always use with. It closes the file automatically even if something goes wrong. We cover how it works in depth in the next file.
readline() — read one line at a time
with open("notes.txt", "r") as file:
line1 = file.readline() # reads the first line
line2 = file.readline() # reads the second line
print(line1)
print(line2)Each call to readline() moves forward one line. Lines include the \n newline character at the end — use .strip() to remove it:
with open("notes.txt", "r") as file:
line = file.readline().strip()
print(line)readlines() — read all lines into a list
with open("notes.txt", "r") as file:
lines = file.readlines()
print(lines)
# ['first line\n', 'second line\n', 'third line\n']
for line in lines:
print(line.strip())Looping directly — the best way for large files
Instead of loading everything into memory at once, loop over the file object directly. Python reads one line at a time — memory efficient:
with open("notes.txt", "r") as file:
for line in file:
print(line.strip())This is the recommended approach for large files. readlines() loads everything into memory — looping directly does not.
A real reading example
Say you have a file students.txt:
Ali,88
Sara,95
Omar,72
Fatima,61
Zainab,90Read and process it:
students = []
with open("students.txt", "r") as file:
for line in file:
name, score = line.strip().split(",")
students.append({"name": name, "score": int(score)})
# find the top student
top = max(students, key=lambda s: s["score"])
average = sum(s["score"] for s in students) / len(students)
print(f"Top student: {top['name']} with {top['score']}")
print(f"Class average: {average:.1f}")Output:
Top student: Sara with 95
Class average: 81.2Writing to a file
write() — write a string
with open("output.txt", "w") as file:
file.write("Hello, world!\n")
file.write("This is line two.\n")
file.write("This is line three.\n")write() does not add a newline automatically — you have to add \n yourself.
After running this, output.txt contains:
Hello, world!
This is line two.
This is line three.writelines() — write a list of strings
lines = [
"First line\n",
"Second line\n",
"Third line\n"
]
with open("output.txt", "w") as file:
file.writelines(lines)writelines() does not add newlines either — include \n in your strings.
A real writing example
Generate a report and save it to a file:
students = [
{"name": "Ali", "score": 88},
{"name": "Sara", "score": 95},
{"name": "Omar", "score": 72},
{"name": "Fatima", "score": 61},
{"name": "Zainab", "score": 90},
]
average = sum(s["score"] for s in students) / len(students)
with open("report.txt", "w") as file:
file.write("=" * 30 + "\n")
file.write(" STUDENT REPORT\n")
file.write("=" * 30 + "\n\n")
for student in students:
grade = "Pass" if student["score"] >= 70 else "Fail"
file.write(f"{student['name']:<10} {student['score']:>5} {grade}\n")
file.write("\n" + "-" * 30 + "\n")
file.write(f"Class Average: {average:.1f}\n")
print("Report saved to report.txt")report.txt will contain:
==============================
STUDENT REPORT
==============================
Ali 88 Pass
Sara 95 Pass
Omar 72 Pass
Fatima 61 Fail
Zainab 90 Pass
------------------------------
Class Average: 81.2Appending to a file
Mode "a" adds content to the end without touching what is already there:
with open("log.txt", "a") as file:
file.write("User logged in at 14:35\n")Run it again — it adds another line. Run it ten times — ten lines. The file grows. Nothing gets overwritten.
A real logging example:
from datetime import datetime
def log_event(event):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open("app.log", "a") as file:
file.write(f"[{timestamp}] {event}\n")
log_event("Server started")
log_event("User Ali logged in")
log_event("User Ali viewed dashboard")
log_event("User Ali logged out")app.log grows over time:
[2026-06-02 14:35:01] Server started
[2026-06-02 14:35:22] User Ali logged in
[2026-06-02 14:36:05] User Ali viewed dashboard
[2026-06-02 14:38:17] User Ali logged outChecking if a file exists before reading
Reading a file that does not exist raises a FileNotFoundError. Check first:
import os
filename = "data.txt"
if os.path.exists(filename):
with open(filename, "r") as file:
print(file.read())
else:
print(f"{filename} does not exist.")Or handle the error directly — cleaner in most cases:
try:
with open("data.txt", "r") as file:
print(file.read())
except FileNotFoundError:
print("File not found.")Working with encoding
Text files use an encoding to store characters. Always specify encoding="utf-8" when working with files that contain non-ASCII characters — names, languages other than English, special symbols:
with open("names.txt", "w", encoding="utf-8") as file:
file.write("محمد علی\n")
file.write("Üniversite\n")
file.write("日本語\n")
with open("names.txt", "r", encoding="utf-8") as file:
print(file.read())Always use encoding="utf-8" when reading or writing text files. If you skip it, Python uses the system default which varies by operating system and can cause UnicodeDecodeError on different machines.
Working with CSV files
CSV (comma-separated values) is one of the most common file formats. Python's built-in csv module handles it cleanly:
import csv
# writing a CSV
students = [
["Name", "Score", "Grade"],
["Ali", 88, "B"],
["Sara", 95, "A"],
["Omar", 72, "C"],
]
with open("students.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerows(students)
# reading a CSV
with open("students.csv", "r", encoding="utf-8") as file:
reader = csv.reader(file)
for row in reader:
print(row)Output:
['Name', 'Score', 'Grade']
['Ali', '88', 'B']
['Sara', '95', 'A']
['Omar', '72', 'C']Using DictReader — each row becomes a dictionary:
with open("students.csv", "r", encoding="utf-8") as file:
reader = csv.DictReader(file)
for row in reader:
print(f"{row['Name']} scored {row['Score']}")Output:
Ali scored 88
Sara scored 95
Omar scored 72Use newline="" when opening CSV files for writing on Windows. Without it, you get an extra blank line between every row.
Binary files
For non-text files — images, PDFs, audio — use binary mode "rb" and "wb":
# copy an image file
with open("photo.jpg", "rb") as source:
data = source.read()
with open("photo_copy.jpg", "wb") as destination:
destination.write(data)file.seek() and file.tell()
You can move around inside an open file:
with open("notes.txt", "r") as file:
print(file.read(5)) # read first 5 characters
print(file.tell()) # current position — 5
file.seek(0) # go back to the beginning
print(file.read(5)) # read first 5 characters againSummary
| Operation | Code |
|---|---|
| Open for reading | open("file.txt", "r") |
| Open for writing | open("file.txt", "w") |
| Open for appending | open("file.txt", "a") |
| Read entire file | file.read() |
| Read one line | file.readline() |
| Read all lines into list | file.readlines() |
| Loop line by line | for line in file: |
| Write a string | file.write("text\n") |
| Write a list of strings | file.writelines(lines) |
| Always use | with open(...) as file: |
| Specify encoding | encoding="utf-8" |