Context Managers

Context managers are one of Python's most elegant and powerful tools — used everywhere from file handling, database transactions, network requests, locks, concurrency, and resource safety.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

If you've ever written with open("file.txt") as f: …you've already used a context manager.

✔ How to create them using generator functions (contextlib.contextmanager)

✔ How real systems use them for safe resource handling

✔ How to build production-grade context managers

✔ How to combine context managers with decorators & advanced design patterns

A context manager controls a setup phase and a cleanup phase.

The moment execution enters the with block, the context manager prepares a resource. When the block exits — even if an error occurs — the resource is cleaned up.

Let's build a simple context manager that logs entering/exiting:

This pattern exists in ORMs like SQLAlchemy & Django:

For simpler cases, Python provides a shortcut.

Locks are native context managers. This pattern protects shared memory in concurrent programs.

You can combine context managers with decorators to automatically wrap function execution:

If __exit__ returns True, exceptions are swallowed.

Never suppress runtime errors silently in real systems.

✔ How to combine decorators and context managers

✔ How to create production-grade resource managers

You can now build and use context managers for any resource lifecycle — files, databases, locks, timers, and more.

Up next: Generators — produce values lazily for memory-efficient data pipelines.

Practice quiz

Which two phases does a context manager control?

  • Compile and run
  • Read and write
  • A setup phase and a cleanup phase
  • Import and export

Answer: A setup phase and a cleanup phase. A context manager manages a setup phase (on entry) and a cleanup phase (on exit).

Which two methods must a class-based context manager define?

  • __enter__ and __exit__
  • __init__ and __del__
  • __aenter__ and __aexit__
  • open and close

Answer: __enter__ and __exit__. Class-based context managers implement __enter__ (entry) and __exit__ (cleanup).

The value returned by __enter__ becomes what?

  • The exception type
  • The return value of the whole block
  • Always None
  • The variable bound by 'as' in the with statement

Answer: The variable bound by 'as' in the with statement. __enter__'s return value is assigned to the 'as' variable in the with statement.

Does __exit__ run if an exception is raised inside the with block?

  • No, exceptions skip cleanup
  • Yes, __exit__ always runs (it's like a finally)
  • Only if you catch the exception first
  • Only for KeyboardInterrupt

Answer: Yes, __exit__ always runs (it's like a finally). __exit__ runs whether the block finishes normally or raises — like a finally clause.

How does __exit__ suppress (swallow) an exception that occurred in the block?

  • By returning True
  • By raising it again
  • By returning None
  • By calling sys.exit()

Answer: By returning True. Returning True from __exit__ tells Python to suppress the exception.

In a @contextmanager generator, where does the cleanup code go?

  • Before the yield
  • In a separate function
  • After the yield
  • In __init__

Answer: After the yield. Setup runs before yield; the cleanup code runs after the yield.

How many times must a @contextmanager generator yield?

  • Zero times
  • Exactly once
  • Twice
  • As many as you like

Answer: Exactly once. It must yield exactly once; zero or multiple yields raise a RuntimeError.

What is the modern way to use two context managers in a single with statement?

  • with A() as a: with B() as b:
  • with A() and B():

with A() as a, B() as b: manages both on one line, avoiding deep nesting.

What does contextlib.ExitStack let you do?

  • Run code faster
  • Manage a dynamic, runtime-determined number of context managers
  • Suppress all exceptions
  • Replace try/except

Answer: Manage a dynamic, runtime-determined number of context managers. ExitStack enters a variable number of context managers and exits them all (in reverse) at block end.

Are threading locks usable directly as context managers with 'with lock:'?

  • No, you must wrap them
  • Only async locks support it
  • Yes, locks are native context managers
  • Only with ExitStack

Answer: Yes, locks are native context managers. Locks implement the context manager protocol, so 'with lock:' acquires and releases automatically.