Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid nested "with" statements when working with multiple files in Python

When working with multiple files in Python code can get ugly when using the recommended style:

with open("foo.txt") as foo:
    with open("bar.txt", "w") as bar:
         with open("baz.txt", "w") as baz:
              # Read from foo, write different output to bar an baz

That's three indentation levels just for working with files! The alternative would be this

foo = open("foo.txt")
bar = open("bar.txt", "w")
baz = open("baz.txt", "w")
# Read from foo, write different output to bar an baz
foo.close()
bar.close()
baz.close()

I have a feeling that either of these examples could be refactored to something more elegant. Any examples?

like image 524
chiborg Avatar asked Nov 04 '14 09:11

chiborg


People also ask

Can you have multiple files open at once Python?

Python provides the ability to open as well as work with multiple files at the same time. Different files can be opened in different modes, to simulate simultaneous writing or reading from these files. An arbitrary number of files can be opened with the open() method supported in Python 2.7 version or greater.

Can you use with Open on multiple files?

The one shortcoming the Open With option has is that it disappears if you select multiple files.

How do you load multiple files in Python?

The importFolder (R)/ import_file (Python) function can be used to import multiple local files by specifying a directory and a pattern. Example patterns include: pattern="/A/.


1 Answers

Python 2.7 and up let you specify multiple context managers in one with statement:

with open("foo.txt") as foo, open("bar.txt", "w") as bar, open("baz.txt", "w") as baz:
    # Read from foo, write different output to bar an baz

The line does get long, and you cannot use parentheses to keep that below 80 characters. You can use \ backslash continuations however:

with open("foo.txt") as foo,\
        open("bar.txt", "w") as bar,\
        open("baz.txt", "w") as baz:
    # Read from foo, write different output to bar an baz

Another option would be to use contextlib.ExitStack() context manager (only in Python 3.3 and up):

from contextlib import ExitStack

with ExitStack() as stack:
    foo = stack.enter_context(open("foo.txt"))
    bar = stack.enter_context(open("bar.txt"))
    baz = stack.enter_context(open("baz.txt"))
like image 56
Martijn Pieters Avatar answered Sep 22 '22 00:09

Martijn Pieters