with statement syntax forces ugly line breaks?

Hi, I can't see a _nice_ way of splitting a with statement over mulitple lines: class FakeContext: def __init__(self, name): self.name = name def __enter__(self): print("enter", self.name) def __exit__(self, *args): print("exit", self.name) with FakeContext("a") as a, FakeContext("b") as b: pass # works fine with FakeContext("a") as a, FakeContext("b") as b: pass # synax error with (FakeContext("a") as a, FakeContext("b") as b): pass # synax error The use case where this mattered to me was this: with open(args.actual, encoding="utf-8") as afh, open(args.expected, encoding="utf-8") as efh: actual = [line.rstrip("\n\r") for line in afh.readlines()] expected = [line.rstrip("\n\r") for line in efh.readlines()] Naturally, I could split the line in an ugly place: with open(args.actual, encoding="utf-8") as afh, open(args.expected, encoding="utf-8") as efh: but it seems a shame to do so. Or am I missing something? I'm using Python 3.1.2. -- Mark Summerfield, Qtrac Ltd, www.qtrac.eu C++, Python, Qt, PyQt - training and consultancy "Rapid GUI Programming with Python and Qt" - ISBN 0132354187 http://www.qtrac.eu/pyqtbook.html

"Gregory P. Smith" <greg@krypto.org> writes:
I agree, especially when we have a much neater continuation mechanism that could work just fine here:: with (FakeContext("a") as a, FakeContext("b") as b): pass -- \ “[Entrenched media corporations will] maintain the status quo, | `\ or die trying. Either is better than actually WORKING for a | _o__) living.” —ringsnake.livejournal.com, 2007-11-12 | Ben Finney

Am 09.09.2010 09:55, schrieb Ben Finney:
No, it could not work just fine. You are basically banning tuples from the context expression (remember that the "as" clause is optional). You would argue that this is not a problem because tuples are not context -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

Am 09.09.2010 09:55, schrieb Ben Finney:
No, it could not work just fine. You are basically banning tuples from the context expression (remember that the "as" clause is optional). Maybe one could argue that this is not a problem because tuples are not context managers anyway, but how would this work then: i = 0 or 1 with (a, b)[i]: Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

Hi Nathan, On Wed, 8 Sep 2010 13:00:25 -0400 Nathan Schneider <nathan@cmu.edu> wrote:
Yes, of course, and that's the way I've done it. But it seems a pity to do it this way when the documentation explicitly discourages the use of the backslash for line continuation: http://docs.python.org/py3k/howto/doanddont.html (look at the very last item)
-- Mark Summerfield, Qtrac Ltd, www.qtrac.eu C++, Python, Qt, PyQt - training and consultancy "Programming in Python 3" - ISBN 0321680561 http://www.qtrac.eu/py3book.html

Am 09.09.2010 07:49, schrieb Mark Summerfield:
Which is actually factually incorrect and should be rewritten. The only situation where stray whitespace after a backslash is valid syntax is within a string literal (and there, there is no alternative). So at least the "stray whitespace leads to silently buggy code" reason not to use backslashes is wrong. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

On Wed, 8 Sep 2010 17:50:29 +0100 Mark Summerfield <mark@qtrac.eu> wrote:
How about: with FakeContext("a") as a: with FakeContext("B") as b: If the double-indent bothers you, using two two-space indents might be acceptable in this case. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Am 08.09.2010 18:50, schrieb Mark Summerfield:
In addition to the backslash hint already given, I'd like to explain why this version isn't allowed: the parser couldn't distinguish between a multi-context with and an expression in parentheses. (In the case of import, where parens can be used around the import list, this is different, no arbitrary expression is allowed.) Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

On Thu, Sep 9, 2010 at 4:07 AM, Georg Brandl <g.brandl@gmx.net> wrote:
I've sometimes wondered if we should consider the idea of making line continuation implicit between keywords and their associated colons. I've never seriously investigated the implications for the parser, though. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Am 09.09.2010 01:19, schrieb Greg Ewing:
That is dangerous, it makes the whitespace rules more complicated. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

On Thu, Sep 9, 2010 at 10:08 PM, Georg Brandl <g.brandl@gmx.net> wrote:
I'm actually not sure it is even *possible* in general to implement my suggestion given the deliberate limitations of Python's parser. Parentheses normally work their indentation-ignoring magic by dropping down into expression evaluation scope where indentation isn't significant (import is a special case where this doesn't quite happen, but it's a rather constrained one). This is definitely a wart in the with statement syntax, but it really isn't clear how best to resolve it. You can at least use parentheses in the individual context expressions, even though you can't wrap the whole thing: .>> from contextlib import contextmanager .>> @contextmanager ... def FakeContext(a): ... yield a ... .>> with FakeContext(1) as x, ( ... FakeContext(2)) as y: ... print(x, y) ... 1 2 Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Wed, Sep 8, 2010 at 5:30 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
I've sometimes wondered if we should consider the idea of making line continuation implicit between keywords and their associated colons.
This would also have the nice aesthetic quality of making colons serve a purpose.

On 09/09/10 00:47, Mike Graham wrote:
Good point! I'm regularly niggled that backslash continuations are needed for long conditional statements where parentheses are not logically necessary (and look disturbingly unpythonic.) There's no ambiguity in allowing statements to extend until the colon, particularly if Greg's "at least as far" indentation rule is applied. +1 from me. Andy

Mark Summerfield wrote:
Why do you need to put everything on one line ? afh = open(args.actual, encoding="utf-8") efh = open(args.expected, encoding="utf-8") with afh, efh: ... In the context of files, the only purpose of the with statement is to close them when leaving the block.
-- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Sep 09 2010)
2010-08-19: Released mxODBC 3.1.0 http://python.egenix.com/ 2010-09-15: DZUG Tagung, Dresden, Germany 6 days to go ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

On 9 September 2010 14:32, M.-A. Lemburg <mal@egenix.com> wrote:
If my understanding is correct (which is perhaps unlikely...), using a single line will close a if opening b fails. Whereas doing them separately before the with statement risks leaving the first un-exited if creating the second fails. Michael

Michael Foord wrote:
Right, but if you stuff everything on a single line, your error handling will have a hard time figuring out which of the two failed to open. I was under the impression that Mark wanted to "protect" the inner block of the with statement, not the context manager creation itself. As usual: hiding away too much stuff in your closet makes things look tidy, but causes a hell of a mess if you ever need to open it again :-)
-- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Sep 09 2010)
2010-08-19: Released mxODBC 3.1.0 http://python.egenix.com/ 2010-09-15: DZUG Tagung, Dresden, Germany 6 days to go ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

On Thu, 09 Sep 2010 15:53:49 +0200 "M.-A. Lemburg" <mal@egenix.com> wrote:
Actually, I was more interested in the aesthetics. I've become habituated to _never_ using \ continuations and found it unsightly to need one here.
:-)
-- Mark Summerfield, Qtrac Ltd, www.qtrac.eu C++, Python, Qt, PyQt - training and consultancy "Programming in Python 3" - ISBN 0321680561 http://www.qtrac.eu/py3book.html

On 9 September 2010 14:53, M.-A. Lemburg <mal@egenix.com> wrote:
If you *need* to distinguish at a higher level then you have no choice. I was really just pointing out that there are *semantic* differences as well, and in fact the code you posted is less safe than the one line version. You lose some of the error handling built-in to context manager creation. Michael

"Gregory P. Smith" <greg@krypto.org> writes:
I agree, especially when we have a much neater continuation mechanism that could work just fine here:: with (FakeContext("a") as a, FakeContext("b") as b): pass -- \ “[Entrenched media corporations will] maintain the status quo, | `\ or die trying. Either is better than actually WORKING for a | _o__) living.” —ringsnake.livejournal.com, 2007-11-12 | Ben Finney

Am 09.09.2010 09:55, schrieb Ben Finney:
No, it could not work just fine. You are basically banning tuples from the context expression (remember that the "as" clause is optional). You would argue that this is not a problem because tuples are not context -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

Am 09.09.2010 09:55, schrieb Ben Finney:
No, it could not work just fine. You are basically banning tuples from the context expression (remember that the "as" clause is optional). Maybe one could argue that this is not a problem because tuples are not context managers anyway, but how would this work then: i = 0 or 1 with (a, b)[i]: Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

Hi Nathan, On Wed, 8 Sep 2010 13:00:25 -0400 Nathan Schneider <nathan@cmu.edu> wrote:
Yes, of course, and that's the way I've done it. But it seems a pity to do it this way when the documentation explicitly discourages the use of the backslash for line continuation: http://docs.python.org/py3k/howto/doanddont.html (look at the very last item)
-- Mark Summerfield, Qtrac Ltd, www.qtrac.eu C++, Python, Qt, PyQt - training and consultancy "Programming in Python 3" - ISBN 0321680561 http://www.qtrac.eu/py3book.html

Am 09.09.2010 07:49, schrieb Mark Summerfield:
Which is actually factually incorrect and should be rewritten. The only situation where stray whitespace after a backslash is valid syntax is within a string literal (and there, there is no alternative). So at least the "stray whitespace leads to silently buggy code" reason not to use backslashes is wrong. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

On Wed, 8 Sep 2010 17:50:29 +0100 Mark Summerfield <mark@qtrac.eu> wrote:
How about: with FakeContext("a") as a: with FakeContext("B") as b: If the double-indent bothers you, using two two-space indents might be acceptable in this case. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Am 08.09.2010 18:50, schrieb Mark Summerfield:
In addition to the backslash hint already given, I'd like to explain why this version isn't allowed: the parser couldn't distinguish between a multi-context with and an expression in parentheses. (In the case of import, where parens can be used around the import list, this is different, no arbitrary expression is allowed.) Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

On Thu, Sep 9, 2010 at 4:07 AM, Georg Brandl <g.brandl@gmx.net> wrote:
I've sometimes wondered if we should consider the idea of making line continuation implicit between keywords and their associated colons. I've never seriously investigated the implications for the parser, though. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Am 09.09.2010 01:19, schrieb Greg Ewing:
That is dangerous, it makes the whitespace rules more complicated. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.

On Thu, Sep 9, 2010 at 10:08 PM, Georg Brandl <g.brandl@gmx.net> wrote:
I'm actually not sure it is even *possible* in general to implement my suggestion given the deliberate limitations of Python's parser. Parentheses normally work their indentation-ignoring magic by dropping down into expression evaluation scope where indentation isn't significant (import is a special case where this doesn't quite happen, but it's a rather constrained one). This is definitely a wart in the with statement syntax, but it really isn't clear how best to resolve it. You can at least use parentheses in the individual context expressions, even though you can't wrap the whole thing: .>> from contextlib import contextmanager .>> @contextmanager ... def FakeContext(a): ... yield a ... .>> with FakeContext(1) as x, ( ... FakeContext(2)) as y: ... print(x, y) ... 1 2 Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Wed, Sep 8, 2010 at 5:30 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
I've sometimes wondered if we should consider the idea of making line continuation implicit between keywords and their associated colons.
This would also have the nice aesthetic quality of making colons serve a purpose.

On 09/09/10 00:47, Mike Graham wrote:
Good point! I'm regularly niggled that backslash continuations are needed for long conditional statements where parentheses are not logically necessary (and look disturbingly unpythonic.) There's no ambiguity in allowing statements to extend until the colon, particularly if Greg's "at least as far" indentation rule is applied. +1 from me. Andy

Mark Summerfield wrote:
Why do you need to put everything on one line ? afh = open(args.actual, encoding="utf-8") efh = open(args.expected, encoding="utf-8") with afh, efh: ... In the context of files, the only purpose of the with statement is to close them when leaving the block.
-- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Sep 09 2010)
2010-08-19: Released mxODBC 3.1.0 http://python.egenix.com/ 2010-09-15: DZUG Tagung, Dresden, Germany 6 days to go ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

On 9 September 2010 14:32, M.-A. Lemburg <mal@egenix.com> wrote:
If my understanding is correct (which is perhaps unlikely...), using a single line will close a if opening b fails. Whereas doing them separately before the with statement risks leaving the first un-exited if creating the second fails. Michael

Michael Foord wrote:
Right, but if you stuff everything on a single line, your error handling will have a hard time figuring out which of the two failed to open. I was under the impression that Mark wanted to "protect" the inner block of the with statement, not the context manager creation itself. As usual: hiding away too much stuff in your closet makes things look tidy, but causes a hell of a mess if you ever need to open it again :-)
-- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Sep 09 2010)
2010-08-19: Released mxODBC 3.1.0 http://python.egenix.com/ 2010-09-15: DZUG Tagung, Dresden, Germany 6 days to go ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

On Thu, 09 Sep 2010 15:53:49 +0200 "M.-A. Lemburg" <mal@egenix.com> wrote:
Actually, I was more interested in the aesthetics. I've become habituated to _never_ using \ continuations and found it unsightly to need one here.
:-)
-- Mark Summerfield, Qtrac Ltd, www.qtrac.eu C++, Python, Qt, PyQt - training and consultancy "Programming in Python 3" - ISBN 0321680561 http://www.qtrac.eu/py3book.html

On 9 September 2010 14:53, M.-A. Lemburg <mal@egenix.com> wrote:
If you *need* to distinguish at a higher level then you have no choice. I was really just pointing out that there are *semantic* differences as well, and in fact the code you posted is less safe than the one line version. You lose some of the error handling built-in to context manager creation. Michael
participants (15)
-
Andy Buckley
-
Ben Finney
-
Georg Brandl
-
Greg Ewing
-
Gregory P. Smith
-
M.-A. Lemburg
-
Mark Summerfield
-
Mathias Panzenböck
-
Michael Foord
-
Mike Graham
-
Mike Meyer
-
MRAB
-
Nathan Schneider
-
Nick Coghlan
-
Terry Reedy