
On Nov 13, 2019, at 10:26, gabriel.kabbe@mail.de wrote:
Hello everybody,
today I tried to open four files simultaneously by writing
with ( open(fname1) as f1, open(fname2) as f2, open(fname3) as f3, open(fname4) as f4 ): ...
However, this results in a SyntaxError which is caused by the extra brackets. Is there a reason that brackets are not allowed in this place?
This has been discussed many times. You probably want to search the archives of -ideas and - dev for the detailed arguments, but from what I remember, it goes something like this:
`with (a, b):` would be ambiguous between two context managers, and a single tuple used as a context manager.
Of course that’s ridiculous. Using a tuple display as a context manager will just raise an exception because tuples aren’t context managers, and it’s hard to imagine why we’d ever want to add the context manager protocol to tuples in the future, so it’s always obvious to any human that this means two context managers, so there’s no reason to consider it ambiguous.
But it does mean either we have to add an extra set of productions to the grammar so we have an “all kinds of expression except parenthesized tuple” to use there, or we have to add a post-grammar, non-declarative rule to disambiguate this case. Both of these are doable, but they do complicate the parser, so the question is, is it worth it?
Nick Coghlan has frequently argued that when you have more than two or three short context managers, that’s a sign you probably want a custom context manager that handles all those things together, or maybe you just want to use ExitStack.
People counter-argue that there are cases where you really do want three mid-length simple context managers, and that’s easily enough to push you over 80 columns, and the backslash looks horrible and is even flagged by some tools even if PEP 8 specifically recommends it here, and turning it into nested with statements makes the code less readable because it highlights the wrong things and indents too far. And in many such cases a custom umbrella manager would just overcomplicate things. If I’m just merging two CSV files into a third one, what meaning or behavior does an object that wraps all three files have? (But maybe ExitStack is fine here?)
So the question is whether people can come up with specific real-life examples that clearly look over complicated done one of the other ways (and ugly done with backslashes), so people can decide whether they’re sufficiently compelling that it’s worth complicating the parser for. And I think it always fizzles out at that point.
But this all based on my memory, which is probably wrong or fuzzy on at least some points, so you really should dig up all of the old threads.