Opening and Closing Files
Python uses the built-in open() function to work with files. The most
important rule: always close files when you're done with them.
# Basic pattern (not recommended)
file = open("example.txt", "r")
content = file.read()
file.close()
# Better: use 'with' statement (auto-closes)
with open("example.txt", "r") as file:
content = file.read()
# File is automatically closed here
with statement
The with statement guarantees the file is closed even if an error
occurs. Forgetting to close files can lead to data loss and resource leaks.
File Modes
The second argument to open() specifies how the file should be opened:
# Read modes
"r" # Read (default) — file must exist
"r+" # Read and write — file must exist
# Write modes
"w" # Write — creates file or OVERWRITES existing
"a" # Append — creates file or adds to end
"x" # Exclusive create — fails if file exists
# Binary modes (add 'b')
"rb" # Read binary (images, PDFs, etc.)
"wb" # Write binary
"w" mode erases everything!
Opening a file with "w" immediately deletes all existing content.
Use "a" to add to a file without losing data.
Reading Files
Read Entire File
with open("notes.txt", "r") as file:
content = file.read()
print(content)
Read Line by Line
# Read all lines into a list
with open("notes.txt", "r") as file:
lines = file.readlines()
for line in lines:
print(line.strip()) # strip() removes trailing newline
# Memory-efficient: iterate directly
with open("notes.txt", "r") as file:
for line in file:
print(line.strip())
file.read() loads the entire file into memory. For large files,
iterate line by line with for line in file: — this reads only one
line at a time.
Read Specific Amount
with open("notes.txt", "r") as file:
first_100 = file.read(100) # Read first 100 characters
next_line = file.readline() # Read next line from current position
Writing Files
Write Text
# Create or overwrite a file
with open("output.txt", "w") as file:
file.write("First line\n")
file.write("Second line\n")
# Write multiple lines at once
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
with open("output.txt", "w") as file:
file.writelines(lines)
Append to a File
# Add to existing file without erasing
with open("log.txt", "a") as file:
file.write("New log entry\n")
Write with print()
with open("output.txt", "w") as file:
print("Hello, file!", file=file)
print(f"The answer is {42}", file=file)
Working with File Paths
import os
from pathlib import Path
# os.path (traditional)
print(os.path.exists("myfile.txt")) # True/False
print(os.path.isfile("myfile.txt")) # True if it's a file
print(os.path.isdir("myfolder")) # True if it's a directory
print(os.path.join("folder", "file.txt")) # folder/file.txt
# pathlib (modern, recommended)
p = Path("folder") / "subfolder" / "file.txt"
print(p) # folder/subfolder/file.txt
print(p.exists()) # True/False
print(p.suffix) # .txt
print(p.stem) # file
print(p.parent) # folder/subfolder
Practical Examples
Log Writer
from datetime import datetime
def log(message, filename="app.log"):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(filename, "a") as file:
file.write(f"[{timestamp}] {message}\n")
log("Application started")
log("User logged in")
log("Error: connection timeout")
Simple CSV Reader
# Reading CSV manually
with open("data.csv", "r") as file:
header = file.readline().strip().split(",")
print(f"Columns: {header}")
for line in file:
values = line.strip().split(",")
row = dict(zip(header, values))
print(row)
# Better: use the csv module
import csv
with open("data.csv", "r") as file:
reader = csv.DictReader(file)
for row in reader:
print(row["name"], row["age"])
Word Counter
def count_words(filename):
with open(filename, "r") as file:
text = file.read()
words = text.split()
lines = text.count("\n") + 1
chars = len(text)
print(f"File: {filename}")
print(f" Lines: {lines}")
print(f" Words: {len(words)}")
print(f" Characters: {chars}")
count_words("example.txt")
Checking If a File Exists
from pathlib import Path
filepath = Path("config.txt")
if filepath.exists():
content = filepath.read_text()
print("File found!")
else:
print("File not found, creating it...")
filepath.write_text("default config")
Summary
- Always use
with open(...) as file:to automatically close files - File modes:
"r"(read),"w"(write/overwrite),"a"(append),"x"(create new) read()loads entire file; iterate withfor line in file:for large fileswrite()andwritelines()write to files; remember\nfor newlines- Use
pathlib.Pathfor modern, cross-platform file path handling - The
csvmodule handles CSV files properly (handles quoting, escaping)
Your programs can now persist data to disk and read external data. Next up: error handling — making your programs robust when things go wrong.