Parenthesized `with` — multiple context managers in one clean block

Today I Learned · August 5, 2026

Parenthesized with — multiple context managers in one clean block

Since Python 3.10 you can wrap the context managers of a with statement in parentheses, so several resources share one block instead of nested with blocks. Same cleanup semantics, flatter code.

The pattern

From a real fixture that hands out a Playwright page and cleans it up on exit:

with (
    sync_playwright() as p,
    p.chromium.launch(headless=True) as browser,
    browser.new_context(viewport={"width": 1280, "height": 720}) as context,
    context.new_page() as page,
):
    page.set_default_timeout(settings.DEFAULT_TIMEOUT)
    yield page

Every context manager enters in order (pbrowsercontextpage) and exits in reverse on the way out — the browser is torn down even if the body raises. Same guarantee as nesting, none of the indentation.

Why it matters

The old way forces one level of nesting per resource:

with sync_playwright() as p:
    with p.chromium.launch(headless=True) as browser:
        with browser.new_context(viewport={"width": 1280, "height": 720}) as context:
            with context.new_page() as page:
                page.set_default_timeout(settings.DEFAULT_TIMEOUT)
                yield page

The parenthesized form is semantically identical to the comma-separated single line with A() as a, B() as b:, just readable across lines. Resources that depend on earlier ones (like page depending on context) read as a pipeline instead of a pyramid.

Gotchas