There are a couple of project that tried to improved heuristic on some
error messages.

Two I can think off are:
   https://github.com/SylvainDe/DidYouMean-Python
and
   https://github.com/dutc/didyoumean

I think that better error messages could be implemented only in the
repl, and/or by alternative repl. Having it as an opt-in library would
be useful to tweak the messages in various context, for example when
used for teaching, or if there are concern about overhead.

Some alternative even already implement heuristic (Recursions error in
IPython are elided with "... last <n> frames repeated, from the frame
below ..." which is way less scarier for beginners. Some other
attempts have been made with attributes error[1] (similar to what
Stephen is proposing), though the traceback info does not have a ref
(or even weakref) on the object on which the attributes access is
made, so even more heuristic have to be made.

Maybe just adding some more information on exception themselves and
giving the recipe of custom except hook would be enough.
Then just allow users to pip-install packages with heuristics ?


-- 
M
[1] https://github.com/ipython/ipython/pull/9073

On Tue, Nov 29, 2016 at 6:14 PM, Stephen J. Turnbull
<turnbull.stephen...@u.tsukuba.ac.jp> wrote:
> Mariatta Wijaya writes:
>
>  > > NameError: name 'length' is not defined
>  >
>  > > A better message might be:
>  >
>  > > Python doesn't recognise the function "length". Did you mean
>  > > len?'
>
> This particular change would be useful to a beginning Python
> programmer.  I've made that error often enough myself (maybe I'm not a
> good example, though, in Lisp the generic function with the same role
> *is* called "length", so I make that error even today).
>
> But I wonder if it's a good example for the generic case.  An error
> message of the form 'Python doesn't recognize the function "<name>".
> Did you mean "<name>"?' could easily be misleading.  Python has
> functions, but they're a type of object.  "length" is a name, which is
> not an object.  The expected type of the object is not function, it's
> callable.  So consider:
>
>     class Blog:
>         pass
>
>     blog = log()
>
>     NameError: Python doesn't recognize the function "log".  Did you
>     mean "Blog"?
>
> I suspect that might cause cognitive dissonance in a beginner who
> thinks of a class as a type or data structure and not as a function.
> And "doesn't recognize the callable" might be awkward (or beginners
> might get used to it very quickly, I don't know).
>
> Also, how do you propose deciding on the alternative to suggest?  In
> this particular case, I expect most developers would agree
> intuitively.  But the Hamming distance is pretty large: 3 of a length
> of 6.  Would you have a dictionary of common errors, and then scan the
> namespace for minimum Hamming distance among defined names with the
> right type of value?
>
> How about:
>
>     class Blog:
>         pass
>
>     blog = get_blog_for_date(someday)
>
>     logn = log(blog.size)
>
>     NameError: Python doesn't recognize the function "log".  Did you
>     mean "Blog"?
>
> Wouldn't
>
>     NameError: Python doesn't recognize the name "log".  Perhaps
>     you need to import the "math" module?
>
> be a better message here?  On second thought, that might imply that
> calling with the unqualified name is generally the best style, and
> teach the beginner to insert
>
>     from math import *
>
> at the top of the module, thus fixing all such errors.  We probably
> don't want that, so maybe
>
>     NameError: Python doesn't recognize the name "log".  There are
>     functions named "log" in the "math" module and the "cmath" module.
>
> would be better yet.
>
> I definitely agree that there are times when Python's error messages
> are quite impenetrable for the beginner, and improvement is
> desirable.  I think that I would probably attack this by looking at
> the builtin namespace and a few stdlib namespaces (math, string, and
> maybe cmath come immediately to mind), and create a dictionary of
> "intuitive beginner errors".  Then trap NameErrors, and preferentially
> emit the message from the dictionary on exact matches.  Actually, come
> to think of it, two dictionaries, one for the builtin namespace, one
> for the selected stdlib, and the following heuristic:
>
>     if name in common_builtin_typos:
>         emit(common_builtin_typos[name])
>     else:
>         errors = small_hamming_distance(name, current_namespace, syntax(name))
>         if errors:
>             emit(errors)
>         else:
>             errors = exact_matches_in_imported_modules(name)
>             if errors:
>                 emit(errors)
>             elif name in common_unimported_stdlib_names:
>                 emit(common_unimported_stdlib_names[name])
>             else:
>                 emit(error_you_would_have_emitted_anyway)
>
> In other words, I don't see a good systematic way to go about this,
> just pile up heuristics (and maybe remove some as they prove
> unuseful!)
>
> Steve
>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas@python.org
> 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/

Reply via email to