Skip to content

Improve name suggestions for NameError/AttributeError by respecting underscore conventions #116871

Closed
@zahlman

Description

@zahlman

Feature or enhancement

Proposal:

Problem description

In more recent versions of Python, for uncaught NameErrors and AttributeErrors, the system tries to suggest names that might have been typoed:

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

However, the suggestion logic apparently does not take underscore conventions into account:

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

Commonly, leading underscores on names are used by convention to mark names that should not be referenced directly in client code. (Of course, it's occasionally necessary or desirable to call dunder methods directly, particularly when inheritance is involved, but generally not outside of classes.)

This has the negative effect, that Python itself could recommend that users invoke undocumented, unstable or unintentional APIs without good reason. One current real-world example of this occurs with Pandas, where version 2.0 removed the append method from DataFrames, but there happens to be an _append method left behind as an implementation detail:

>>> import pandas as pd
>>> pd.DataFrame().append
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/lib/python3.11/site-packages/pandas/core/generic.py", line 6296, in __getattr__
    return object.__getattribute__(self, name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'DataFrame' object has no attribute 'append'. Did you mean: '_append'?

Proposal

I propose that: when the invalid identifier or attribute name does not already start with an underscore, valid names that do start with an underscore should be excluded from suggestions. As mentioned in the linked discussion, there is already precedent for this -

  1. As implemented by help:
>>> import pydoc
>>> pydoc.pager = print # to simplify behaviour for the example
>>> class Example:
...     __slots__ = [] # to simplify behaviour for the example
...     def method(self): pass
...     def _method(self): pass
... 
>>> help(Example)
Help on class Example in module __main__:

class Example(builtins.object)
 |  Methods defined here:
 |  
 |  method(self)


>>>
  1. When using star-imports:
>>> _, name, result = 1, 2, {}
>>> exec('from __main__ import *', result)
>>> '_' in result
False
>>> 'name' in result
True

It still makes sense IMO to suggest underscore names when the invalid name already starts with an underscore - even mixing and matching single- and double-underscore cases. For example, _init_ is a very plausible typo for __init__, especially for beginners who are learning from a book or an old PDF.

Has this already been discussed elsewhere?

I have already discussed this feature proposal on Discourse

Links to previous discussion of this feature:

https://discuss.python.org/t/name-suggestions-for-attributeerrors-and-possibly-nameerrors-should-not-include-names-with-single-leading-underscores/48588

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions