OSPython.022: Context Managers and the with Statement Basics

OSPython.022 cover showing a VS Code Dark+ Python example using with open and a three-step open, use, automatic cleanup diagram

A context manager handles setup and cleanup around a block of Python code.

The easiest example is a file. You open it, use it, and then it needs to be closed. Python’s with statement lets that cleanup happen automatically when the block ends.

Start with the smallest useful example

with open("scores.txt", "r") as file:
    data = file.read()

print(data)

Read it in plain English:

  1. Open scores.txt.
  2. Call the opened file file.
  3. Read the file inside the indented block.
  4. Leave the block.
  5. Python closes the file through the file object’s context-management behavior.

Visual model: enter → use → exit

┌──────────────────┐     ┌──────────────────┐     ┌────────────────────┐
│ 1. ENTER / SETUP │  →  │ 2. USE RESOURCE  │  →  │ 3. EXIT / CLEANUP  │
│ open the file    │     │ read the file    │     │ close the file     │
└──────────────────┘     └──────────────────┘     └────────────────────┘
          ___________________ with block ___________________/

Visual learning diagram: a context manager surrounds the work with a controlled entry and exit.

That is the main idea. Everything else in this lesson explains how Python makes that pattern work.

Why not just call close() yourself?

You can write:

file = open("scores.txt", "r")
data = file.read()
file.close()

But cleanup becomes easier to forget as code grows. An error can also interrupt the normal path through the program. A context manager puts the resource-management rule around the block that uses the resource.

Python’s language reference says the with statement wraps a block using methods supplied by a context manager, and if entry succeeds, the corresponding exit method is called when the block is left.

Video 1: What the with statement really does

This focused lesson explains what Python’s with statement is doing around a block of code.

The two important methods

A class can participate in a normal with statement by implementing the context-manager protocol. The two names to recognize are:

  • __enter__() — runs when Python enters the context.
  • __exit__() — runs when Python leaves the context.
with SomeContext() as thing:
     │
     ├── __enter__() runs
     │
     ├── indented block runs
     │
     └── __exit__() runs when the block is left

Visual model: enter establishes the context; exit performs the matching cleanup or exit work.

A tiny custom context manager

class GameSession:
    def __enter__(self):
        print("Session started")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("Session ended")
        return False

with GameSession() as session:
    print("Playing Hash Race")

Output:

Session started
Playing Hash Race
Session ended

The important part is the order: enter → work → exit.

What does “as” mean?

In this example:

with GameSession() as session:

the value returned by __enter__() is assigned to session. With files, the opened file object is what you normally use after as.

Video 2: Context managers and the with statement

This tutorial reinforces with, context managers, and the enter/exit lifecycle.

What if an error happens inside the block?

Python passes exception information to __exit__() when the block is being left because of an exception. That gives the context manager a chance to perform its exit work even when the normal flow was interrupted.

For a beginner, remember this:

ENTER
  ↓
USE RESOURCE
  ↓
normal finish OR exception
  ↓
EXIT / CLEANUP

Whether an exception is then allowed to continue depends on what __exit__() returns. Returning a false value, including False or None, does not suppress the exception. Returning a true value tells the with machinery that the exception was handled.

How this connects to the earlier file lesson

OSPython.007: Reading and Writing Files introduced file operations. This lesson explains why the with open(...) pattern is so useful: the file object is a context manager that handles its exit behavior for you.

Context managers are not only for files

The same pattern can manage many kinds of resources or temporary states. Examples include locks, database connections, temporary directories, and other resources that need a clear beginning and end.

The exact setup and cleanup depend on the context manager. The common idea stays the same:

with resource_manager() as resource:
    # use the resource here
    pass

# exit work has happened here

Video 3: What exactly is a Python context manager?

This visual explanation reinforces the resource-management idea behind Python context managers.

A useful connection to generators and decorators

Python’s contextlib module includes a @contextmanager decorator. It can turn a specially written generator function into a context manager. This connects two recent lessons—decorators and generators—to the idea in this lesson.

from contextlib import contextmanager

@contextmanager
def game_session():
    print("Session started")
    try:
        yield
    finally:
        print("Session ended")

with game_session():
    print("Playing Hash Race")

You do not need to memorize this version yet. The important connection is that yield marks where the body of the with block runs, while the code around it handles entry and exit work.

Common beginner mistakes

  • Thinking with is only special syntax for files.
  • Forgetting that the indented block defines the active context.
  • Assuming __exit__() means every exception is automatically ignored.
  • Manually calling __enter__() and __exit__() when a normal with statement is clearer.
  • Putting code that still needs the resource after the with block has ended.

Quick practice

  1. Create a small text file named score.txt.
  2. Open it with with open("score.txt", "r") as file:.
  3. Read and print the contents inside the block.
  4. Draw the three boxes: ENTER → USE → EXIT.
  5. Explain which method corresponds to entering and which corresponds to exiting a custom context manager.
  6. Explain why resource cleanup is easier to reason about when it is attached to the context.

Key takeaway

A Python context manager defines what should happen when code enters and leaves a controlled context. The with statement makes that lifecycle easy to use. Start by remembering one visual: ENTER → USE → EXIT/CLEANUP.

Leave a comment