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...@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...@python.org <javascript:> > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/