[Python-ideas] Arguments to exceptions

Neil Girdhar mistersheik at gmail.com
Thu Jul 6 14:26:41 EDT 2017


This is a good example.  I like this idea.  I think that a good place to 
start would be setting the right example in the standard library: 
IndexError could have the offending index, KeyError the offending key, 
TypeError the offending type, etc.

On Monday, July 3, 2017 at 3:49:23 PM UTC-4, Jeff Walker wrote:
>
> Paul, 
>      I think you are fixating too much on Ken's example. I think I 
> understand what he 
> is saying and I agree with him. It is a problem I struggle with routinely. 
> It occurs in 
>  the following situations: 
>
> 1. You are handling an exception that you are not raising. This could be 
> because 
>     Python itself is raising the exception, as in Ken's example, or it 
> could be raised 
>     by some package you did not write. 
> 2. You need to process or transform the message in some way. 
>
> Consider this example: 
>
>     import json                                                           
>             
>                                                                           
>         
>     >>> s = '{"abc": 0, "cdf: 1}'                                         
>                 
>                                                                           
>         
>     >>> try:                                                               
>               
>     ...     d = json.loads(s)                                             
>                 
>     ... except Exception as e:                                             
>               
>     ...     print(e)                                                       
>               
>     ...     print(e.args) 
>     Unterminated string starting at: line 1 column 12 (char 11) 
>     ('Unterminated string starting at: line 1 column 12 (char 11)',) 
>
> Okay, I have caught an exception for which I have no control over how the 
> exception was raised. Now, imagine that I am writing an application that 
> highlights 
> json errors in place. To do so, I would need the line and column numbers 
> to 
> highlight the location of the error, and ideally I'd like to strip them 
> from the base 
> message and just show that. You can see from my second print statement 
> that 
> the line and column numbers were not passed as separate arguments. Thus 
> I need to parse the error message to extract them. Not a difficult job, 
> but fragile. 
> Any change to the error message could break my code. 
>
> I don't know what this code smell is that people keep referring to, but to 
> me, 
> that code would smell. 
>
> Jeff 
>
>
> > On 3 July 2017 at 09:59, Ken Kundert <python... at shalmirane.com 
> <javascript:>> wrote: 
> > > I think in trying to illustrate the existing behavior I made things 
> more 
> > > confusing than they needed to be.  Let me try again. 
> > > 
> > > Consider this code. 
> > > 
> > >     >>> import Food 
> > >     >>> try: 
> > >     ...     import meals 
> > >     ... except NameError as e: 
> > >     ...     name = str(e).split("'")[1]   # <-- fragile code 
> > >     ...     from difflib import get_close_matches 
> > >     ...     candidates = ', '.join(get_close_matches(name, Food.foods, 
> 1, 0.6)) 
> > >     ...     print(f'{name}: not found. Did you mean {candidates}?') 
> > > 
> > > In this case *meals* instantiates a collection of foods. It is a 
> Python file, 
> > > but it is also a data file (in this case the user knows Python, so 
> Python is 
> > > a convenient data format). In that file thousands of foods may be 
> instantiated. 
> > > If the user misspells a food, I would like to present the available 
> > > alternatives. To do so, I need the misspelled name.  The only way I 
> can get it 
> > > is by parsing the error message. 
> > 
> > As Steven pointed out, this is a pretty good example of a code smell. 
> > My feeling is that you may have just proved that Python isn't quite as 
> > good a fit for your data file format as you thought - or that your 
> > design has flaws. Suppose your user had a breakfast menu, and did 
> > something like: 
> > 
> >     if now < lunchtim: # Should have been "lunchtime" 
> > 
> > Your error handling will be fairly confusing in that case. 
> > 
> > > That is the problem.  To write the error handler, I need the 
> misspelled name. 
> > > The only way to get it is to extract it from the error message. The 
> need to 
> > > unpack information that was just packed suggests that the packing was 
> done too 
> > > early.  That is my point. 
> > 
> > I don't have any problem with *having* the misspelled name as an 
> > attribute to the error, I just don't think it's going to be as useful 
> > as you hope, and it may indeed (as above) encourage people to use it 
> > without thinking about whether there might be problems with using 
> > error handling that way. 
> > 
> > > Fundamentally, pulling the name out of an error message is a really 
> bad coding 
> > > practice because it is fragile.  The code will likely break if the 
> formatting or 
> > > the wording of the message changes.  But given the way the exception 
> was 
> > > implemented, I am forced to choose between two unpleasant choices: 
> pulling the 
> > > name from the error message or not giving the enhanced message at all. 
> > 
> > Or using a different approach. ("Among our different approaches...!" 
> > :-)) Agreed that's also an unpleasant choice at this point. 
> > 
> > > What I am hoping to do with this proposal is to get the Python 
> developer 
> > > community to see that: 
> > > 1. The code that handles the exception benefits from having access to 
> the 
> > >    components of the error message.  In the least it can present the 
> message to 
> > >    the user is the best possible way. Perhaps that means enforcing a 
> particular 
> > >    style, or presenting it in the user's native language, or perhaps 
> it means 
> > >    providing additional related information as in the example above. 
> > 
> > I see it as a minor bug magnet, but not really a problem in principle. 
> > 
> > > 2. The current approach to exceptions follows the opposite philosophy, 
> > >    suggesting that the best place to construct the error message is at 
> the 
> > >    source of the error. It inadvertently puts obstacles in place that 
> make it 
> > >    difficult to customize the message in the handler. 
> > 
> > It's more about implicitly enforcing the policy of "catch errors over 
> > as small a section of code as practical". In your example, you're 
> > trapping NameError from anywhere in a "many thousands" of line file. 
> > That's about as far from the typical use of one or two lines in a try 
> > block as you can get. 
> > 
> > > 3. Changing the approach in the BaseException class to provide the 
> best of both 
> > >    approaches provides considerable value and is both trivial and 
> backward 
> > >    compatible. 
> > 
> > A small amount of value in a case we don't particularly want to 
> encourage. 
> > Whether it's trivial comes down to implementation - I'll leave that to 
> > whoever writes the PR to demonstrate. (Although if it *is* trivial, is 
> > it something you could write a PR for?) 
> > 
> > Also, given that this would be Python 3.7 only, would people needing 
> > this functionality (only you have expressed a need so far) be OK with 
> > either insisting their users go straight to Python 3.7, or including 
> > backward compatible code for older versions? 
> > 
> > Overall, I'm -0 on this request (assuming it is trivial to implement - 
> > I certainly don't feel it's worth significant implementation effort). 
> > 
> > Paul 
> _______________________________________________ 
> Python-ideas mailing list 
> Python... at python.org <javascript:> 
> https://mail.python.org/mailman/listinfo/python-ideas 
> Code of Conduct: http://python.org/psf/codeofconduct/ 
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170706/935cc572/attachment.html>


More information about the Python-ideas mailing list