"except;" - semicolon after except, to get rid of indentation when doing error recovery

Sometimes it would be useful to be able to write: def foo(): try: return thing() except ValueError; try: return otherthing() except ValueError; try: return yetotherthing() except ValueError; if shouldraise(): raise But currently this needs to be written like so: def foo(): try: return thing() except ValueError: try: return otherthing() except ValueError: try: return yetotherthing() except ValueError: if shouldraise(): raise Look at all that unnecessary indentation! Would be nice to get rid of it.

On Wed, Jun 16, 2021 at 10:51 AM Soni L. <fakedme+py@gmail.com> wrote:
Dangerous idea - my first interpretation of that syntax was that it would be equivalent to "except ValueError: pass", which would be very confusing (it's subtly different in your example with return, and drastically different in other cases). Are you doing this sort of thing a lot? And if you are, do you actually need/want the exception chaining that comes from burying more and more code into the except clauses? I know this is just a trivial example, but I'd be looking to see if it can be done with a loop instead. def foo(): for func in (thing, otherthing, yetotherthing): try: return func() except ValueError: pass or something like that. ChrisA

Sorry - personally I think this is absolutely ugly :-) So I will bikeshed. If this thread even go ahead - since the idea is not that bad, maybe allowing `try` on the same line? Then it would be inline with `elif` - but still structured "English like" try: statement except ValueError try: statement2 except TypeError: ... I had sometimes needed 2 and maybe up to 3 levels of this, nothing 'blocker', but maybe, just maybe, it would not be bad. However, in real life, usually one wants to put more statements on the `except` clause than a bare nested try block. (logging, etc...) On Tue, 15 Jun 2021 at 21:58, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Jun 16, 2021 at 10:56:12AM +1000, Chris Angelico wrote:
Aside from the difference in chained exceptions (the exception cause or context, I forget which is which, will be different) surely it is the same as `except ValueError: pass`? TBH I thought that difference was so minor that it wasn't even worth mentioning. -- Steve

On Wed, Jun 16, 2021 at 11:45 AM Steven D'Aprano <steve@pearwood.info> wrote:
That's the subtle difference. The drastic difference is that, if you ever change one of the cases (deliberately or accidentally) so it doesn't have the return, it'll daisychain - but only when that one gets hit. But logically, there is a significant difference between putting code inside the except block, and having "except X: pass" and then putting code after. Code should be written the way it's meant to be, not the way that happens to work. ChrisA

On Tue, Jun 15, 2021 at 09:48:48PM -0300, Soni L. wrote:
It would be nice to use better looking four-space indents with indented blocks: def foo(): try: return thing() except ValueError: try: return otherthing() except ValueError: try: return yetotherthing() except ValueError: if shouldraise(): raise That makes the block structure of the code more clear, it reflects the semantics of the code better, it is much easier to modify (if we add an extra line between one of the try keywords and the returns, we don't need to change any existing lines, we just insert a new one: smaller diffs and better diffs). And it makes it more obvious that there is no final return (perhaps we forgot to add it?) and that the interpreter will automatically return None when we fall off the end of the function. But if none of those arguments convince you that ideomatic Python code is better Python code, that's okay too. You can remove almost all the indentation: def foo(): try: return thing() except ValueError: pass try: return otherthing() except ValueError: pass try: return yetotherthing() except ValueError: if shouldraise(): raise -- Steve

On Wed, Jun 16, 2021 at 10:51 AM Soni L. <fakedme+py@gmail.com> wrote:
Dangerous idea - my first interpretation of that syntax was that it would be equivalent to "except ValueError: pass", which would be very confusing (it's subtly different in your example with return, and drastically different in other cases). Are you doing this sort of thing a lot? And if you are, do you actually need/want the exception chaining that comes from burying more and more code into the except clauses? I know this is just a trivial example, but I'd be looking to see if it can be done with a loop instead. def foo(): for func in (thing, otherthing, yetotherthing): try: return func() except ValueError: pass or something like that. ChrisA

Sorry - personally I think this is absolutely ugly :-) So I will bikeshed. If this thread even go ahead - since the idea is not that bad, maybe allowing `try` on the same line? Then it would be inline with `elif` - but still structured "English like" try: statement except ValueError try: statement2 except TypeError: ... I had sometimes needed 2 and maybe up to 3 levels of this, nothing 'blocker', but maybe, just maybe, it would not be bad. However, in real life, usually one wants to put more statements on the `except` clause than a bare nested try block. (logging, etc...) On Tue, 15 Jun 2021 at 21:58, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Jun 16, 2021 at 10:56:12AM +1000, Chris Angelico wrote:
Aside from the difference in chained exceptions (the exception cause or context, I forget which is which, will be different) surely it is the same as `except ValueError: pass`? TBH I thought that difference was so minor that it wasn't even worth mentioning. -- Steve

On Wed, Jun 16, 2021 at 11:45 AM Steven D'Aprano <steve@pearwood.info> wrote:
That's the subtle difference. The drastic difference is that, if you ever change one of the cases (deliberately or accidentally) so it doesn't have the return, it'll daisychain - but only when that one gets hit. But logically, there is a significant difference between putting code inside the except block, and having "except X: pass" and then putting code after. Code should be written the way it's meant to be, not the way that happens to work. ChrisA

On Tue, Jun 15, 2021 at 09:48:48PM -0300, Soni L. wrote:
It would be nice to use better looking four-space indents with indented blocks: def foo(): try: return thing() except ValueError: try: return otherthing() except ValueError: try: return yetotherthing() except ValueError: if shouldraise(): raise That makes the block structure of the code more clear, it reflects the semantics of the code better, it is much easier to modify (if we add an extra line between one of the try keywords and the returns, we don't need to change any existing lines, we just insert a new one: smaller diffs and better diffs). And it makes it more obvious that there is no final return (perhaps we forgot to add it?) and that the interpreter will automatically return None when we fall off the end of the function. But if none of those arguments convince you that ideomatic Python code is better Python code, that's okay too. You can remove almost all the indentation: def foo(): try: return thing() except ValueError: pass try: return otherthing() except ValueError: pass try: return yetotherthing() except ValueError: if shouldraise(): raise -- Steve
participants (5)
-
Chris Angelico
-
Joao S. O. Bueno
-
Soni L.
-
Stephen J. Turnbull
-
Steven D'Aprano