Create a "with" block on several context managers?
contextmanager, python, with-statement
Solution
In Python 2.7 and 3.1 and above, you can write:
with A() as X, B() as Y, C() as Z:
do_something()
This is normally the best method to use, but if you have an unknown-length list of context managers you'll need one of the below methods.
In Python 3.3, you can enter an unknown-length list of context managers by using `contextlib.ExitStack`:
with ExitStack() as stack:
for mgr in ctx_managers:
stack.enter_context(mgr)
# ...
This allows you to create the context managers as you are adding them to the `ExitStack`, which prevents the possible problem with `contextlib.nested` (mentioned below).
contextlib2 provides a backport of `ExitStack` for Python 2.6 and 2.7.
In Python 2.6 and below, you can use `contextlib.nested`:
from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
do_something()
is equivalent to:
m1, m2, m3 = A(), B(), C()
with m1 as X:
with m2 as Y:
with m3 as Z:
do_something()
Note that this isn't exactly the same as normally using nested `with`, because `A()`, `B()`, and `C()` will all be called initially, before entering the context managers. This will not work correctly if one of these functions raises an exception.
`contextlib.nested` is deprecated in newer Python versions in favor of the above methods.
Problem
Suppose you have three objects you acquire via context manager, for instance A lock, a db connection and an ip socket. You can acquire them by: ``` with lock: with db_con: with socket: #do stuff ``` But is there a way to do it in one block? something like ``` with lock,db_con,socket: #do stuff ``` Furthermore, is it possible, given an array of unknown length of objects that have context managers, is it possible to somehow do: ``` a=[lock1, lock2, lock3, db_con1, socket, db_con2] with a as res: #now all objects in array are acquired ``` If the answer is "no", is it because the need for such a feature implies bad design, or maybe I should suggest it in a pep? :-P