Re: [Python-ideas] Block-Scoped Exception Handlers

It looks frankly a bit like an "on error goto errorhandler" statement but with a few drawbacks to that. How can you indicate the 'exception handled block' should end, when there's no indentation level involved? It would force the exception block to service all code until the end of that indentation level but what happens on within the indentation level is defined by other more functional criteria. The proposed construct could not replace the normal try/catch syntax because of that, but it can also not mix with the normal syntax well because it's too similar to it and hence confusing. The gain of the proposed construct seems to be to save 1 indentation level. Even when this would be worth the cost it would be more logical to still put the except block at the end of the functional block. So instead of the proposed: def process_todo(todo): except Exception, e: raise OverallTodoError("Not expected") from e with Timer("todo processing"): # pre-processing for t in todo: except Exception, e: raise TodoError("oh dear!") from e # do error p the below is more logical, since the main code remains the focus and the exception the afterthought: def process_todo(todo): with Timer("todo processing"): # pre-processing for t in todo: except Exception, e: raise TodoError("oh dear!") from e # do error p except Exception, e: raise OverallTodoError("Not expected") from e But this all leaves something implicit rather then implicit: the start (or in the proposal: the end) of the exception block. Robert
Message: 3 Date: Wed, 4 May 2016 15:58:58 -0400 From: Kyle Lahnakoski <klahnakoski@mozilla.com> To: python-ideas@python.org Subject: [Python-ideas] Block-Scoped Exception Handlers Message-ID: <00d21501-60fd-d756-c8a6-906a8b235221@mozilla.com> Content-Type: text/plain; charset=windows-1252
Please excuse my nomenclature. I hope the community can correct the synonyms that clarify my proposal.
Problem -------
I program defensively, and surround many of my code blocks with try blocks to catch expected and unexpected errors. Those unexpected errors seem to dominate in my code; I never really know how many ways my SQL library can fail, nor am I really sure that a particular key is in a `dict()`. Most of the time I can do nothing about those unexpected errors; I simply chain them, with some extra description about what the code block was attempting to do.
I am using 2.7, so I have made my own convention for chaining exceptions. 3.x chains more elegantly:
for t in todo: try: # do error prone stuff except Exception, e: raise ToDoError("oh dear!") from e
The ?error prone stuff? can itself have more try blocks to catch known failure modes, maybe deal with them. Add some `with` blocks and a conditional, and the nesting gets ugly:
def process_todo(todo): try: with Timer("todo processing"): # pre-processing for t in todo: try: # do error prone stuff except Exception, e: raise TodoError("oh dear!") from e # post-processing except Exception, e: raise OverallTodoError("Not expected") from e
Not only is my code dominated by exception handling, the meaningful code is deeply nested.
Solution --------
I would like Python to have a bare `except` statement, which applies from that line, to the end of enclosing block (or next `except` statement). Here is the same example using the new syntax:
def process_todo(todo): except Exception, e: raise OverallTodoError("Not expected") from e
with Timer("todo processing"): # pre-processing for t in todo: except Exception, e: raise TodoError("oh dear!") from e
# do error prone stuff # post-processing
Larger code blocks do a better job of portraying he visual impact of the reduced indentation. I would admit that some readability is lost because the error handling code precedes the happy path, but I believe the eye will overlook this with little practice.
Multiple `except` statements are allowed. They apply as if they were used in a `try` statement; matched in the order declared:
def process_todo(todo): pre_processing() # has no exception handling
except SQLException, e: # effective until end of method raise Exception("Not expected") from e except Exception, e: raise OverallTodoError("Oh dear!") from e
processing()
A code block can have more than one `except` statement:
def process_todo(todo): pre_processing() # no exception handling
except SQLException, e: # covers lines from here to beginning of next except statement raise Exception("Not expected") from e except Exception, e: # catches other exception types raise Exception("Oh dear!") from e
processing() # Exceptions caught
except SQLException, e: # covers a lines to end of method raise Exception("Happens, sometimes") from e
post_processing() # SQLException caught, but not Exception
In these cases, a whole new block is effectively defined. Here is the same in legit Python:
def process_todo(todo): pre_processing() # no exception handling
try: processing() # Exceptions caught except SQLException, e: # covers all lines from here to beginning of next except statement raise Exception("Not expected") from e except Exception, e: # catches other exception types raise Exception("Oh dear!") from e
try: post_processing() # SQLException caught, but not Exception except SQLException, e: # covers a lines to end of method raise Exception("Happens, sometimes") from e
Other Thoughts --------------
I only propose this for replacing `try` blocks that have no `else` or `finally` clause. I am not limiting my proposal to exception chaining; Anything allowed in `except` clause would be allowed.
I could propose adding `except` clauses to each of the major statement types (def, for, if, with, etc?). which would make the first example look like:
def process_todo(todo): with Timer("todo processing"): # pre-processing for t in todo: # do error prone stuff except Exception, e: raise TodoError("oh dear!") from e
# post-processing except Exception, e: raise OverallTodoError("Not expected") from e
But, I am suspicious this is more complicated than it looks to implement, and the `except` statement does seem visually detached from the block it applies to.
Thank you for your consideration!
------------------------------
Subject: Digest Footer
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
------------------------------
End of Python-ideas Digest, Vol 114, Issue 35 *********************************************

Oh dear! It appears I screwed up the indentation. Since I never see the emails I send to this list, I have no idea what you all were looking at. Maybe I should have used underscores for email: def process_todo(todo): ____except Exception, e: ________raise OverallTodoError("Not expected") from e ____with Timer("todo processing"): ________# pre-processing ________for t in todo: ____________except Exception, e: ________________raise TodoError("oh dear!") from e ____________# do error prone stuff ________# post-processing The exception handling code should be indented, but the code it applies to is not. On 5/4/2016 6:45 PM, Robert van Geel wrote:
It looks frankly a bit like an "on error goto errorhandler" statement but with a few drawbacks to that.
How can you indicate the 'exception handled block' should end, when there's no indentation level involved? It would force the exception block to service all code until the end of that indentation level but what happens on within the indentation level is defined by other more functional criteria. The proposed construct could not replace the normal try/catch syntax because of that, but it can also not mix with the normal syntax well because it's too similar to it and hence confusing.
The gain of the proposed construct seems to be to save 1 indentation level. Even when this would be worth the cost it would be more logical to still put the except block at the end of the functional block. So instead of the proposed:
def process_todo(todo): except Exception, e: raise OverallTodoError("Not expected") from e with Timer("todo processing"): # pre-processing for t in todo: except Exception, e: raise TodoError("oh dear!") from e
# do error p
the below is more logical, since the main code remains the focus and the exception the afterthought:
def process_todo(todo): with Timer("todo processing"): # pre-processing for t in todo: except Exception, e: raise TodoError("oh dear!") from e
# do error p
except Exception, e: raise OverallTodoError("Not expected") from e
But this all leaves something implicit rather then implicit: the start (or in the proposal: the end) of the exception block.
Robert
Message: 3 Date: Wed, 4 May 2016 15:58:58 -0400 From: Kyle Lahnakoski <klahnakoski@mozilla.com> To: python-ideas@python.org Subject: [Python-ideas] Block-Scoped Exception Handlers Message-ID: <00d21501-60fd-d756-c8a6-906a8b235221@mozilla.com> Content-Type: text/plain; charset=windows-1252
Please excuse my nomenclature. I hope the community can correct the synonyms that clarify my proposal.
Problem -------
I program defensively, and surround many of my code blocks with try blocks to catch expected and unexpected errors. Those unexpected errors seem to dominate in my code; I never really know how many ways my SQL library can fail, nor am I really sure that a particular key is in a `dict()`. Most of the time I can do nothing about those unexpected errors; I simply chain them, with some extra description about what the code block was attempting to do.
I am using 2.7, so I have made my own convention for chaining exceptions. 3.x chains more elegantly:
for t in todo: try: # do error prone stuff except Exception, e: raise ToDoError("oh dear!") from e
The ?error prone stuff? can itself have more try blocks to catch known failure modes, maybe deal with them. Add some `with` blocks and a conditional, and the nesting gets ugly: def process_todo(todo): try: with Timer("todo processing"): # pre-processing for t in todo: try: # do error prone stuff except Exception, e: raise TodoError("oh dear!") from e # post-processing except Exception, e: raise OverallTodoError("Not expected") from e
Not only is my code dominated by exception handling, the meaningful code is deeply nested.
Solution --------
I would like Python to have a bare `except` statement, which applies from that line, to the end of enclosing block (or next `except` statement). Here is the same example using the new syntax:
def process_todo(todo): except Exception, e: raise OverallTodoError("Not expected") from e with Timer("todo processing"): # pre-processing for t in todo: except Exception, e: raise TodoError("oh dear!") from e
# do error prone stuff # post-processing
Larger code blocks do a better job of portraying he visual impact of the reduced indentation. I would admit that some readability is lost because the error handling code precedes the happy path, but I believe the eye will overlook this with little practice.
Multiple `except` statements are allowed. They apply as if they were used in a `try` statement; matched in the order declared:
def process_todo(todo): pre_processing() # has no exception handling
except SQLException, e: # effective until end of method raise Exception("Not expected") from e except Exception, e: raise OverallTodoError("Oh dear!") from e
processing()
A code block can have more than one `except` statement:
def process_todo(todo): pre_processing() # no exception handling except SQLException, e: # covers lines from here to beginning of next except statement raise Exception("Not expected") from e except Exception, e: # catches other exception types raise Exception("Oh dear!") from e processing() # Exceptions caught except SQLException, e: # covers a lines to end of method raise Exception("Happens, sometimes") from e post_processing() # SQLException caught, but not Exception In these cases, a whole new block is effectively defined. Here is the same in legit Python:
def process_todo(todo): pre_processing() # no exception handling try: processing() # Exceptions caught except SQLException, e: # covers all lines from here to beginning of next except statement raise Exception("Not expected") from e except Exception, e: # catches other exception types raise Exception("Oh dear!") from e try: post_processing() # SQLException caught, but not Exception except SQLException, e: # covers a lines to end of method raise Exception("Happens, sometimes") from e Other Thoughts --------------
I only propose this for replacing `try` blocks that have no `else` or `finally` clause. I am not limiting my proposal to exception chaining; Anything allowed in `except` clause would be allowed. I could propose adding `except` clauses to each of the major statement types (def, for, if, with, etc?). which would make the first example look like:
def process_todo(todo): with Timer("todo processing"): # pre-processing for t in todo: # do error prone stuff except Exception, e: raise TodoError("oh dear!") from e # post-processing except Exception, e: raise OverallTodoError("Not expected") from e
But, I am suspicious this is more complicated than it looks to implement, and the `except` statement does seem visually detached from the block it applies to.
Thank you for your consideration!
------------------------------
Subject: Digest Footer
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
------------------------------
End of Python-ideas Digest, Vol 114, Issue 35 *********************************************
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

To mitigate my indentation disaster, I posted the document on Github. https://github.com/klahnakoski/Block-Scoped-Exception-Handlers On 5/4/2016 6:45 PM, Robert van Geel wrote:
How can you indicate the 'exception handled block' should end, when there's no indentation level involved? It would force the exception block to service all code until the end of that indentation level but what happens on within the indentation level is defined by other more functional criteria. The proposed construct could not replace the normal try/catch syntax because of that, but it can also not mix with the normal syntax well because it's too similar to it and hence confusing.
participants (2)
-
Kyle Lahnakoski
-
Robert van Geel