Re: [Python-ideas] Consistent programming error handling idiom

The example is removed from its original context. The point was to show that there is no reason to locally catch AssertionError (contrast with AttributeError, ValueError, TypeError, etc.). AssertionError is *always* indicative of a bug (unlike AttributeError which only may be indicative of a bug).
This leads to disaster in the case of buggy code. This leads to a greater disaster when the boundary allows the code to continue running. It's not a black and white thing, there is no 100% way to detect for buggy code but my argument is that you shouldn't ignore an assert when you're lucky enough to get one.
I'm not saying except-log is to blame for buggy code. I'm saying that when an exception occurs, there's no way to tell whether it was caused by an internal bug or an external error. Except-log should normally be limited to exceptions caused by external errors in production code.
Yes it may be bad design or the code may have bugs but that's precisely the point. By the time the exception hits your catch-all, there's no universal way of determining whether or not the exception was due to an internal bug (or bad design or whatever) or an external error.
The alternative I'm suggesting is to reset that flight computer and switch to the backup one (potentially written by a different team).
Context managers don't allow me to determine whether an exception is caused by an internal bug or external error, so it's not a solution to this problem. I want to live in a world where I can do this: while cbs: cb = cbs.pop() try: cb() except Exception as e: logging.exception("In main loop") if is_a_bug(e): raise SystemExit() from e Python may be able to do something here. One possible thing is a new exception hierarchy, there may be other solutions. This may be sufficient but I doubt it: def is_a_bug(e): return isinstance(e, AssertionError) The reason I am polling python-ideas is that I can't be the only one who has ever encountered this deficiency in Python. Rian

On Sat, Apr 09, 2016 at 04:28:47AM +1000, Chris Angelico wrote:
ANY uncaught exception is a bug.
What, even SystemExit and KeyboardInterrupt?
Any caught exception is not a bug.
Even: try: ... except: # Look, bug free programming! pass I am sure that any attempt to make universal rules about what is or isn't a bug will be doomed to failure. Remember that people can write code like this: # Writing a BASIC interpreter in Python. if not isinstance(command[0], int): raise SyntaxError('expected line number') So, no, SyntaxError does not necessarily mean a bug in your code. *ALL* exceptions have to be understood in context, you can't just make a sweeping generalisation that exception A is always a bug, exception B is always recoverable. It depends on the context. -- Steve

On Sat, Apr 9, 2016 at 5:01 AM, Steven D'Aprano <steve@pearwood.info> wrote:
In terms of a boundary location? Yes, probably. If you're writing a web server that allows web applications to be plugged into it, you probably want to let the console halt processing of one request, then go back and handle another. Although it is contextual; you might choose the other way, in which case it's "any uncaught subclass of Exception is a bug", or "anything other than KeyboardInterrupt is a bug", or some other definition. I'm on the fence about SystemExit; in any context where there's this kind of boundary, sys.exit() simply wouldn't be used. So it could viably be called a bug, or it could validly be used to terminate the entire server.
As far as the boundary location's concerned, yes. The inner code can be as ridiculous as it likes, but the boundary will never do the "log and resume" if all exceptions are caught. (It won't even get an opportunity to.)
If one escapes to a boundary, then yes it does. That's the context we're talking about here. ChrisA

On Fri, Apr 8, 2016 at 11:24 AM, <rian@thelig.ht> wrote:
And I think we can say the same thing about ALL Exceptions --even a syntax error may not be a "stop everything" error in a system that runs user-written scripts. I agree with Chris A's point: Any unhandled Exception is a bug. Simple as that. Any other interpretation would be a style issue, decided for your group/application. And if you are going to go there, I would do: if not_a_bug() instead. Consistent with the principle of good Python code -- only handle the Exceptions you know to handle. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

I'm happy with that interpretation. If that was codified in a style document accessible to newbies I think that would help achieve a more consistent approach to exceptions. Yet something dark and hideous inside me tells me except-log loops will continue to be pervasive and bugs will continue to be ignored in a large number of Python programs.

On Fri, Apr 8, 2016 at 12:47 PM, Rian Hunter <rian@thelig.ht> wrote:
it already is in advice all over the place: "don't use bare except" Doesn't mean folks don't do it anyway.... -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

On 04/08/2016 01:50 PM, Rian Hunter wrote:
I think bare except is different from "except Exception" which is common and not discouraged. "except Exception" still masks programming errors.
And comes with the advice to "log it, research it". -- ~Ethan~

On 08/04/2016 21:50, Rian Hunter wrote:
I think bare except is different from "except Exception" which is common and not discouraged. "except Exception" still masks programming errors.
"except Exception" is a programming error as far as I'm concerned, but I'm not expecting my own code to keep running 24/7/365. Horses for courses. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence

On Fri, Apr 08, 2016 at 11:24:15AM -0700, rian@thelig.ht wrote:
And I want a pony :-) So long as Python allows people to write code like this: # A deliberately silly example if len(seq) == 0: raise ImportError("assertion fails") you cannot expect to automatically know what an exception means without any context of where it came from and why it happened. The above example is silly, but it doesn't take much effort to come up with more serious ones: - an interpreter written in Python may raise SyntaxError, which is not a bug in the interpreter; - a test framework may raise AssertionError for a failed test, which is not a bug in the framework; - a function may raise MemoryError if the call *would* run out of memory, but without actually running out of memory; consequently it is not a fatal error, while another function may raise the same MemoryError because it actually did fatally run out of memory. Effectively, you want the compiler to Do What I Mean when it comes to exceptions. DWIM may, occasionally, be a good idea in applications, but I maintain it is never a good idea in a programming language. http://www.catb.org/jargon/html/D/DWIM.html I'm afraid that there's no hope for it: you're going to have to actually understand where an exception came from, and why it happened, before deciding whether or not it can be recovered from. The interpreter can't do that for you. -- Steve

On Sat, Apr 09, 2016 at 04:28:47AM +1000, Chris Angelico wrote:
ANY uncaught exception is a bug.
What, even SystemExit and KeyboardInterrupt?
Any caught exception is not a bug.
Even: try: ... except: # Look, bug free programming! pass I am sure that any attempt to make universal rules about what is or isn't a bug will be doomed to failure. Remember that people can write code like this: # Writing a BASIC interpreter in Python. if not isinstance(command[0], int): raise SyntaxError('expected line number') So, no, SyntaxError does not necessarily mean a bug in your code. *ALL* exceptions have to be understood in context, you can't just make a sweeping generalisation that exception A is always a bug, exception B is always recoverable. It depends on the context. -- Steve

On Sat, Apr 9, 2016 at 5:01 AM, Steven D'Aprano <steve@pearwood.info> wrote:
In terms of a boundary location? Yes, probably. If you're writing a web server that allows web applications to be plugged into it, you probably want to let the console halt processing of one request, then go back and handle another. Although it is contextual; you might choose the other way, in which case it's "any uncaught subclass of Exception is a bug", or "anything other than KeyboardInterrupt is a bug", or some other definition. I'm on the fence about SystemExit; in any context where there's this kind of boundary, sys.exit() simply wouldn't be used. So it could viably be called a bug, or it could validly be used to terminate the entire server.
As far as the boundary location's concerned, yes. The inner code can be as ridiculous as it likes, but the boundary will never do the "log and resume" if all exceptions are caught. (It won't even get an opportunity to.)
If one escapes to a boundary, then yes it does. That's the context we're talking about here. ChrisA

On Fri, Apr 8, 2016 at 11:24 AM, <rian@thelig.ht> wrote:
And I think we can say the same thing about ALL Exceptions --even a syntax error may not be a "stop everything" error in a system that runs user-written scripts. I agree with Chris A's point: Any unhandled Exception is a bug. Simple as that. Any other interpretation would be a style issue, decided for your group/application. And if you are going to go there, I would do: if not_a_bug() instead. Consistent with the principle of good Python code -- only handle the Exceptions you know to handle. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

I'm happy with that interpretation. If that was codified in a style document accessible to newbies I think that would help achieve a more consistent approach to exceptions. Yet something dark and hideous inside me tells me except-log loops will continue to be pervasive and bugs will continue to be ignored in a large number of Python programs.

On Fri, Apr 8, 2016 at 12:47 PM, Rian Hunter <rian@thelig.ht> wrote:
it already is in advice all over the place: "don't use bare except" Doesn't mean folks don't do it anyway.... -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

On 04/08/2016 01:50 PM, Rian Hunter wrote:
I think bare except is different from "except Exception" which is common and not discouraged. "except Exception" still masks programming errors.
And comes with the advice to "log it, research it". -- ~Ethan~

On 08/04/2016 21:50, Rian Hunter wrote:
I think bare except is different from "except Exception" which is common and not discouraged. "except Exception" still masks programming errors.
"except Exception" is a programming error as far as I'm concerned, but I'm not expecting my own code to keep running 24/7/365. Horses for courses. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence

On Fri, Apr 08, 2016 at 11:24:15AM -0700, rian@thelig.ht wrote:
And I want a pony :-) So long as Python allows people to write code like this: # A deliberately silly example if len(seq) == 0: raise ImportError("assertion fails") you cannot expect to automatically know what an exception means without any context of where it came from and why it happened. The above example is silly, but it doesn't take much effort to come up with more serious ones: - an interpreter written in Python may raise SyntaxError, which is not a bug in the interpreter; - a test framework may raise AssertionError for a failed test, which is not a bug in the framework; - a function may raise MemoryError if the call *would* run out of memory, but without actually running out of memory; consequently it is not a fatal error, while another function may raise the same MemoryError because it actually did fatally run out of memory. Effectively, you want the compiler to Do What I Mean when it comes to exceptions. DWIM may, occasionally, be a good idea in applications, but I maintain it is never a good idea in a programming language. http://www.catb.org/jargon/html/D/DWIM.html I'm afraid that there's no hope for it: you're going to have to actually understand where an exception came from, and why it happened, before deciding whether or not it can be recovered from. The interpreter can't do that for you. -- Steve
participants (7)
-
Chris Angelico
-
Chris Barker
-
Ethan Furman
-
Mark Lawrence
-
Rian Hunter
-
rian@thelig.ht
-
Steven D'Aprano