Most elegant way to handle nested context managers in Python 3.13?

I’ve been experimenting with Python 3.13’s new features and ran into an interesting pattern question.

When dealing with multiple nested context managers (like opening several files, database connections, and temporary directories), what’s the most Pythonic approach these days?

# The old way gets deeply nested
with open("a.txt") as f1:
    with open("b.txt") as f2:
        with tempfile.TemporaryDirectory() as tmp:
            # actual work here
            pass

I know about contextlib.ExitStack and the with a, b, c: syntax, but I’m curious if there are newer patterns or if people have strong preferences. What do you all use in production?

I’m a big ExitStack fan, where multiple context managers are genuinely needed.

But similar to your example, shutil.copy2, and if reading files that fit into memory, pathlib.Path.read_text, .write_text and the two _bytes methods (or even
Path.open) have all vastly reduced the number of with open()s I write.

You can pass a tuple of context managers to with:

with (
    open(...) as f1,
    open(...) as f2,
):
    # do things

I use this in production, but if you have a bunch of context managers and the hierarchy matters, this can be confusing to read.

Edit: I see you already know this one, they do need to be in a tuple if you’re going to assign them though I believe.

I didn’t know you could do that… hell yes.