In 3.3+, ExitStack is definitely the answer; in fact, it's the first example given in the docs:
with ExitStack() as stack:
files = [stack.enter_context(open(path) for path in path_list]
for f in files:
do_something(f)
Of course if your with body is really just a loop over files, there's no reason to do this—just put a with statement for each file inside the loop. (In fact, there's a good reason not to do this—why open a possibly unbounded number of file handles at once just to use them one at a time?) But presumably your real code needs to use multiple files at the same time.
In earlier versions, you can easily just borrow ExitStack from the 3.3 source. Backporting to 3.2 is trivial; for 2.7, you need to strip out (or rewrite, if you need it) the stuff that gets fancy with exception propagation to guarantee you the right exception contexts, but that's pretty easy.
However, an even better solution is probably to install contextlib2 off PyPI, which "provides backports of features in the latest version of the standard library’s contextlib module to earlier Python versions." Then you can just use contextlib2.ExitStack instead of contextlib.ExitStack. (In fact, contextlib2 had ExitStack, under its preliminary name ContextStack, before Python 3.3 did…)
But you can also easily build a closing_all context manager, similar to the stdlib's closing but for multiple things:
@contextlib.contextmanager
def closing_all(things):
try:
yield things
finally:
for thing in things:
thing.close()
If you need to deal with things whose close method can raise, you need to be a little smarter—but with file objects, and most other types you'd using with closing, you don't need that.
The bigger problem is that if any open can raise an exception, it's hard to find any valid sequence you can actually pass as the things argument. But if that's not a problem, using it is even simpler than ExitStack:
with closing_all(open(path) for path in path_list) as files:
for f in fs:
do_something(f)
You could also build an opening_all(paths, mode='r') that does the opens for you and wraps them in a closing_all, but I don't think that adds much.
Of course if you need to do this often, the best answer is to build opening_all around ExitStack and not even bother with closing_all.
contextlib.ExitStackthat you can use - see docs.python.org/3/library/… - This means that only if all files are openable does the block execute - rather than looping over each file and finding somewhere through that an open error occurs...