What they are

Context managers ensure that setup and cleanup code runs automatically. The with statement is the most common way to use them.

File handling

The most common use—automatically closes files:

# Without context manager (must remember to close):
file = open('data.txt', 'r')
content = file.read()
file.close()  # Easy to forget!

# With context manager (auto-closes):
with open('data.txt', 'r') as file:
    content = file.read()
# File automatically closed here, even if error occurs

Creating your own

Use a class with __enter__ and __exit__ methods:

class Timer:
    def __enter__(self):
        import time
        self.start = time.time()
        return self
    
    def __exit__(self, *args):
        import time
        print(f"Took {time.time() - self.start:.2f} seconds")

# Use it:
with Timer():
    # Do something
    time.sleep(1)

Using contextlib

For simpler cases, use contextlib.contextmanager:

from contextlib import contextmanager

@contextmanager
def timer():
    import time
    start = time.time()
    yield
    print(f"Took {time.time() - start:.2f} seconds")

with timer():
    time.sleep(1)

Why use context managers

  • Automatic cleanup (files, connections, locks)
  • Error-safe (cleanup happens even if error occurs)
  • Cleaner code (no manual cleanup needed)
  • Resource management (prevents leaks)