MOD-26 · Sequence #26 · Practical Python

Python File Handling

File operations in Python must be safely managed to avoid OS file descriptor leaks. The with statement (context managers) guarantees that files are closed automatically upon exiting the block, even if unexpected runtime errors occur.

Live Interactive Code Snippet (Python 3.12 CPython WASM) Open in Practice Mode →
# File handling using with context manager
with open("test.txt", "w") as f:
    f.write("Python File Handling\n")

Core Principles & Mental Models

1. File Modes & Context Managers (`with open(...)`)

Deterministic Resource Release

  • Modes: "r" (read, default), "w" (write, truncates file), "a" (append), "r+" (read/write), "b" (binary mode like "rb" or "wb").
  • The `with open(...) as f:` syntax binds a context manager.
  • Upon exiting the block (by finishing, return, or exception), Python automatically invokes `f.__exit__()`, flushing buffers and closing the file descriptor.
# Demonstrating file operations with context manager
content = "Line 1: Computer Science\nLine 2: Data Structures\n"
# Reading line by line
for line in content.splitlines():
    print("Processed:", line)
💡 Key Takeaway: Always use with open(...) to ensure file descriptors are never leaked in memory.

2. The Context Manager Protocol (__enter__ & __exit__)

Building Custom Context Managers

  • Any class implementing `__enter__()` and `__exit__(exc_type, exc_val, exc_tb)` is a valid context manager.
  • `__enter__` prepares the resource and returns the binding value for the `as` target.
  • `__exit__` handles cleanup. Returning `True` from `__exit__` suppresses any exception raised inside the with block.
class ExecutionTimer:
    import time
    def __enter__(self):
        self.start = self.time.time()
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.duration = self.time.time() - self.start
        print(f"Elapsed time: {self.duration:.4f}s")
        return False

with ExecutionTimer():
    total = sum(range(100_000))
💡 Key Takeaway: Context managers simplify resource acquisition and release patterns (locks, files, sockets, database transactions).

Interactive Walkthrough Examples

Safe File Reading with Line Iteration (Basic)

Iterating over file streams line by line without loading the entire file into memory.

sample_data = "alpha,10\nbeta,20\ngamma,30"
# Simulating streaming line processing
total = 0
for line in sample_data.splitlines():
    parts = line.strip().split(",")
    if len(parts) == 2:
        name, val = parts[0], int(parts[1])
        total += val
        print(f"Read {name}: {val}")
print("Total sum:", total)

Explanation: Streaming lines avoids reading gigabytes of data into RAM at once.

Common Misconceptions & Exam Traps

Common Pitfall: Opening Files Without the `with` Statement

If errors occur between open() and close(), the file handle remains open in the OS table until process termination.

Buggy Code
f = open("data.txt", "w")
f.write("Important data")
# If an exception occurs here, f.close() is never called, leaking the file handle!
f.close()
Correct Solution
with open("data.txt", "w") as f:
    f.write("Important data")
# Guaranteed closed automatically under all circumstances

Exam Trap Note: Exams strictly require context managers (`with open`) for all file I/O operations.

Conceptual Knowledge Self-Check Quiz

Q1: Which method on a context manager is guaranteed to execute upon exiting a `with` block?

  1. __close__()
  2. __exit__()
  3. __finally__()
  4. __terminate__()

The context manager protocol calls `__exit__()` automatically whenever execution leaves the with block.

Algorithmic Practice Challenges

Idiomatic Best Practices

  • ✅ Always specify explicit encoding: `open("data.txt", "r", encoding="utf-8")`.
  • ✅ Never read an entire large file with `.read()` when you can stream lines with `for line in f:`.

All 26 Curriculum Modules