This question already has an answer here:
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
The first part of your question is possible in Python 3.1.
Following on from @sage88's response you can always assign those patches to have meaningful variable names before you enter into them.
You could create those patches in multiple lines
In Python 2.7 and 3.1 and above, you can write:
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:
This allows you to create the context managers as you are adding them to the
ExitStack
, which prevents the possible problem withcontextlib.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
:is equivalent to:
Note that this isn't exactly the same as normally using nested
with
, becauseA()
,B()
, andC()
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.@interjay's Answer is correct. However, if you need to do this for long context managers, for example mock.patch context managers, then you quickly realize you want to break this across lines. Turns out you can't wrap them in parens, so you have to use backslashes. Here's what that looks like:
The second part of your question is solved with
contextlib.ExitStack
in Python 3.3.