Suggestions could consider standard library module names as well

First, I think the “did you mean” feature is really cool and will be very helpful, as I’ve spent a good amount of time helping students spot spelling errors in their code.

I ran into the suggestions a few time in shell today when I forgot to import a module:

>>> stream = io.StringIO()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'io' is not defined. Did you mean 'id'?

I suggest that it can consider standard library module names for suggestions, so the experience would look like:

>>> stream = io.StringIO()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'io' is not defined. Did you mean 'id'? Or did you forget to import 'io'?

It seems to me that it will be fairly common for users to forget to import a module. It may throw them off to see a suggestion like ‘id’ so I think it’d help to acknowledge the very real other possibility that they meant to import a module instead.

What do you think? I believe it’d involve a change to cpython/suggestions.c at 27b989403356ccdd47545a93aeab8434e9c69f21 · python/cpython (github.com) to consider library names as well.

5 Likes

Based on the comments on Typo hint message for from-imports? · Issue #91058 · python/cpython · GitHub, I suspect that the answer given will be that it is not easily feasible as it would slow down cPython too much for the average user.

If you and your students want more helpful suggestions, may I suggest to look at friendly? Here is how friendly deals with this case (I use friendly with the default iPython-style prompt below):

friendly-traceback: 0.6.6
friendly: 0.6.0
Python: 3.10.2
Type 'Friendly' for help on special functions/methods.


[1]: stream = io.StringIO()

Traceback (most recent call last):
  Code block [1], line 1
    stream = io.StringIO()
NameError: name 'io' is not defined. Did you mean: 'id'?

Did you mean id?

[2]: why()

The name `io` is not defined in your program. Perhaps you forgot to import `io` which
is found in Python's standard library.

The Python builtin `id` has a similar name.

`io` is a name found in the following modules from the standard library: bz2,
configparser, dbm, dis, getpass, gzip, logging, lzma, mailbox, modulefinder,
pathlib, pdb, pickle, pickletools, pyclbr, pydoc, runpy, site, smtplib, socket,
subprocess, tarfile, typing, zipfile. Perhaps you forgot to import `io` from one of
these modules.

As you can see, it included the additional suggestion you thought of and, in this particular case, quite a few other ones.

2 Likes

Why would slow down cpython? Doesn’t this only happen when you’re already raising a NameError, which is extremely rare?

Thanks for linking to that thread, very interesting. That seems to be a slightly different situation since that’s specifically about ImportErrors, whereas I’m requesting it for NameError (where it already is). My naive implementation would be to hardcode the std modules list and compare to that. I still wouldn’t be surprised if there was a performance hit for it in some way, of course.

As for friendly-traceback, that looks great! However, I have students working in quite a range of environments - Jupyter, CoLab, Pyodide, VSCode, etc, so I’d need to show them how to install it in all those places (or somehow do it for them). Still a possibility though!

The other drawback is that a student could get too used to friendly-traceback and have a hard time using Python without it, but that’s a question of pedagogy that I don’t have an answer for.

https://docs.python.org/3/library/sys.html#sys.stdlib_module_names

Raising an exception is already costly, but unlike exceptions like StopIteration and KeyError, NameError is not often expected and caught. If your buggy program takes 20ms to fail and raise instead of 15ms, is anyone going to care?

(Ironically, I do catch NameError, usually for feature detection, especially in older code that had to run under both Python 2 and 3. But that’s just a one-off cost when the module loads so I don’t think it will affect me too much.)

I don’t think the extra cost will be prohibitive, but actually trying it and measuring the performance hit is the only way to be sure.

I think that extending suggestions to stdlib modules is a good idea, especially for students.

The main downside is that we all know what comes next:

“Why can’t the suggestion also check for third-party modules in the search path too?”

:slight_smile:

@rhettinger what do you think about this as an aid to students?

1 Like