The with Statement · Examples
Core Python

The with Statement Examples

Short, runnable programs that show python with statement in action. Read the explanation, press Run, then change the code and try your own ideas. New to the topic? Start with the Python with Statement lesson.

1A stopwatch without a real clock

A class-based context manager that measures how many clock ticks pass inside the block. The clock here is a fake counter so the output is predictable; with real code you would call time.perf_counter() in the same two places.

A stopwatch without a real clock
import itertools

clock = itertools.count(0, 5)

class Stopwatch:
    def __enter__(self):
        self.start = next(clock)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.elapsed = next(clock) - self.start

with Stopwatch() as quick:
    pass
with Stopwatch() as slow:
    for _ in range(3):
        next(clock)
print(quick.elapsed, slow.elapsed)
Expected output5 20

2Change a setting for one block only

A @contextmanager function sets a value, yields, and restores the old value in finally. The theme comes back even though the second block raises an error.

Change a setting for one block only
from contextlib import contextmanager

settings = {"theme": "light"}

@contextmanager
def temporary(key, value):
    old = settings[key]
    settings[key] = value
    try:
        yield
    finally:
        settings[key] = old

with temporary("theme", "dark"):
    print("Inside:", settings["theme"])

try:
    with temporary("theme", "contrast"):
        raise RuntimeError("render failed")
except RuntimeError:
    print("Error handled")
print("Outside:", settings["theme"])
Expected outputInside: dark
Error handled
Outside: light

3Commit or roll back a transaction

__enter__ takes a backup. If the block finishes normally, __exit__ commits; if it raises, the backup is restored. Returning False lets the error continue to the caller, who decides how to react.

Commit or roll back a transaction
class Transaction:
    def __init__(self, accounts):
        self.accounts = accounts

    def __enter__(self):
        self.backup = dict(self.accounts)
        return self.accounts

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is None:
            print("commit")
        else:
            self.accounts.clear()
            self.accounts.update(self.backup)
            print("rollback:", exc_value)
        return False

bank = {"asha": 100, "ben": 20}

with Transaction(bank) as db:
    db["asha"] -= 30
    db["ben"] += 30

try:
    with Transaction(bank) as db:
        db["asha"] -= 500
        if db["asha"] < 0:
            raise ValueError("insufficient funds")
except ValueError:
    pass
print(bank)
Expected outputcommit
rollback: insufficient funds
{'asha': 70, 'ben': 50}

4A file that lives in memory

io.StringIO behaves like an open text file but keeps everything in memory. print(..., file=report) writes into it, and getvalue() returns all the text. You can also read from one, exactly like a real file.

A file that lives in memory
import io

report = io.StringIO()
print("Sales report", file=report)
for city, total in [("Pune", 75), ("Leeds", 20)]:
    print(f"{city:<6}{total:>4}", file=report)

text = report.getvalue()
print(text, end="")

with io.StringIO(text) as source:
    first = source.readline().strip()
    rest = source.read().splitlines()
print(first, "+", len(rest), "rows")
Expected outputSales report
Pune    75
Leeds   20
Sales report + 2 rows

5Capture what a function prints

redirect_stdout temporarily points print() at a buffer. This is a common way to test functions that print instead of returning a value. Normal printing resumes after the block.

Capture what a function prints
import io
from contextlib import redirect_stdout

def print_receipt(items):
    for name, price in items:
        print(f"{name}: {price:.2f}")
    print("Total:", sum(price for _, price in items))

buffer = io.StringIO()
with redirect_stdout(buffer):
    print_receipt([("tea", 2.5), ("cake", 4.0)])

captured = buffer.getvalue().splitlines()
print(captured)
print("Lines captured:", len(captured))
Expected output['tea: 2.50', 'cake: 4.00', 'Total: 6.5']
Lines captured: 3

6Two files at once, and ignoring a missing one

One with statement can hold several context managers: the source is read while the target is written. suppress(FileNotFoundError) skips the cleanup quietly if the old backup does not exist.

Two files at once, and ignoring a missing one
import os
from contextlib import suppress

with open("names.txt", "w") as f:
    f.write("asha\nben\nchen\n")

with open("names.txt") as source, open("titles.txt", "w") as target:
    for line in source:
        target.write(line.strip().title() + "\n")

with open("titles.txt") as f:
    print(f.read().split())

with suppress(FileNotFoundError):
    os.remove("old_backup.txt")
print("Cleanup finished")
Expected output['Asha', 'Ben', 'Chen']
Cleanup finished

Practise next

Python with Statement exercises → Back to the lesson

Python Exceptions: try, except, else and finally examplesPython File Handling examplesPython pathlib examplesPython Class Methods and Static Methods examples