Create a with block on several context managers?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python allows multiple context managers in a single with statement. That is usually the cleanest answer when you need several resources to be acquired together, such as files, locks, database transactions, or temporary directories.
Basic Syntax
The simplest form is a comma-separated list of context managers.
This is equivalent to nested with blocks, but it is flatter and easier to read.
Both forms call the __enter__ methods from left to right and the __exit__ methods in reverse order.
Why the Exit Order Matters
Reverse cleanup order is important when resources depend on one another. Imagine acquiring a lock and then opening a file used inside the protected section.
Python enters lock first and open(...) second. On exit, the file closes before the lock releases. That matches the usual expectation that inner resources are cleaned up before outer coordination objects disappear.
Aliases Are Optional Per Manager
Not every context manager needs an as target. In the previous example, the lock does not produce a value that we need to bind, but the file does.
This also works with more than two managers.
Each manager behaves independently; Python just combines the setup and teardown logic into one readable statement.
When the Number of Managers Is Dynamic
A plain with statement is best when you know the managers at code-writing time. If the number is dynamic, use contextlib.ExitStack.
ExitStack gives you the same cleanup guarantee, but lets you add managers programmatically. That is the right tool when files, sockets, or transactions are discovered at runtime.
Exception Behavior
If one of the later context managers fails during entry, Python will still exit the managers that were already entered successfully. That is another reason to prefer a real with statement over manual try and finally code.
In that example, first is still exited even though second fails during __enter__.
Style Guidance
Use a single combined with when the resources conceptually belong to one operation. If the setup logic is complicated or each resource needs its own comments, nested blocks can still be clearer.
The goal is not to compress everything into one line. The goal is to make acquisition and cleanup rules obvious.
Common Pitfalls
A common mistake is trying to build a dynamic number of managers with a plain comma-separated with. That only works for a fixed set known ahead of time. Use ExitStack when the list is built at runtime.
Another mistake is misunderstanding exit order. Cleanup happens in reverse order, so if resource ordering matters, put the outermost resource first.
Also avoid replacing context managers with manual close() calls unless you have a strong reason. It is easy to miss exception paths and leak resources.
Summary
- Python supports multiple context managers in one
withstatement. - Entry happens from left to right, and exit happens in reverse order.
- A combined
withis equivalent to nestedwithblocks, but often easier to read. - Use
contextlib.ExitStackwhen the number of managers is dynamic. - Prefer real context management over manual cleanup code.

