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
⚠️
Always use the 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())
💡
For large files, iterate directly

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 with for line in file: for large files
  • write() and writelines() write to files; remember \n for newlines
  • Use pathlib.Path for modern, cross-platform file path handling
  • The csv module handles CSV files properly (handles quoting, escaping)
🎉
File I/O unlocked!

Your programs can now persist data to disk and read external data. Next up: error handling — making your programs robust when things go wrong.