It is unclear what you’re proposing here. That might be related to my second point: the screenshot of a REPL session is unreadable for me. Please post as text instead of an image.
__dir__() is simply not called and in __slots__ you get an error:
>>> class MyClass:
... __slots__ = (1, "ab1", "ab2")
...
Traceback (most recent call last):
File "<python-input-29>", line 1, in <module>
class MyClass:
...<3 lines>...
self.ab2 = None
TypeError: __slots__ items must be strings, not 'int'
On this, it is the limit for the attribute “__slots__”. The method “__dir__” has no limits, while the function dir() has a limit that it should be sortable.
Define this class to show:
Running Release|x64 interpreter...
Python 3.15.0a0 (heads/main-dirty:aba04d18785, Oct 18 2025, 20:58:01) [MSC v.1944 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class MyClass:
... __slots__ = ("ab1", "ab2")
... def __dir__(self):
... return [1, "ab1", "ab2"]
...
>>> a = MyClass()
>>> a.abc
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
a.abc
AttributeError: 'MyClass' object has no attribute 'abc'. Did you mean: 'ab1'?
Wrong value returnd from 'MyClass.__dir__'
Please ensure that what is returned is sequence of strings
>>> a.ab1
Traceback (most recent call last):
File "<python-input-3>", line 1, in <module>
a.ab1
AttributeError: 'MyClass' object has no attribute 'ab1'
Wrong value returnd from 'MyClass.__dir__'
Please ensure that what is returned is sequence of strings
'ab1' found in the list of attribute of the obj but cannot get. Please check the code in the class 'MyClass'
>>> def wrong_dir(self):
... raise TypeError("cannot get all attribute on it")
...
>>> MyClass.__dir__ = wrong_dir
>>> a.abc
Traceback (most recent call last):
File "<python-input-6>", line 1, in <module>
a.abc
AttributeError: 'MyClass' object has no attribute 'abc'. Did you mean: 'ab1'?
Exception ignored in calling obj.__dir__:
Traceback (most recent call last):
File "C:\Users\hh180\my_python\cpython\Lib\traceback.py", line 1803, in _compute_suggestion_error
d = obj.__dir__() if not isinstance(obj, type) else type(obj).__dir__(obj)
~~~~~~~~~~~^^
File "<python-input-4>", line 2, in wrong_dir
raise TypeError("cannot get all attribute on it")
TypeError: cannot get all attribute on it
>>> a.ab1
Traceback (most recent call last):
File "<python-input-7>", line 1, in <module>
a.ab1
AttributeError: 'MyClass' object has no attribute 'ab1'
Exception ignored in calling obj.__dir__:
Traceback (most recent call last):
File "C:\Users\hh180\my_python\cpython\Lib\traceback.py", line 1803, in _compute_suggestion_error
d = obj.__dir__() if not isinstance(obj, type) else type(obj).__dir__(obj)
~~~~~~~~~~~^^
File "<python-input-4>", line 2, in wrong_dir
raise TypeError("cannot get all attribute on it")
TypeError: cannot get all attribute on it
'ab1' found in the list of attribute of the obj but cannot get. Please check the code in the class 'MyClass'
>>>
Here is all of the code:
#1
class MyClass:
__slots__ = ("ab1", "ab2")
def __dir__(self):
return [1, "ab1", "ab2"]
#2
a = MyClass()
a.abc
a.ab1
#3
def wrong_dir(self):
raise TypeError("cannot get all attribute on it")
MyClass.__dir__ = wrong_dir
#4
a.abc
a.ab1
Show the effect of the repl is to show that the note is different fron the original exception: they cannot be raised or the interpreter will collapse.
So you want a.ab1 to pass, even though no __getattr__ is defined, and ab1 is only part of the __slots__? When an attribute is defined in __slots__, but not for the instance itself, it doesn’t exist.
class c:
__slots__ = ("a", "b", "c")
c().abc
Here we get the following (expected error):
Traceback (most recent call last):
File "main.py", line 5, in <module>
c().abc
AttributeError: 'c' object has no attribute 'abc'
(Note that this is run online).
But I agree with you, (if that’s what you’re trying to say), that the error message(s) could be improved here. Trying to access an attribute that is present in __slots__, but not for the object itself, could instead raise an error like: AttributeError: 'c' object has no attribute 'abc'. Perhaps you forgot to set the value?
If all of the attributes are given from the method “__dir__”, may be it is not only “forget to set”. What python hopes first is that the object’s “__getattr__” is suitable with “__dir__”. We get the list of the attributes from “__dict__”, “__slots__” and “__class__.__dict__” only when the method “__dir__” was called failed.
But __dict__ does not exist when you have __slots__ (that’s why it exists, to save memory).
And yeah, in your example, __dir__ fails[1], which is why Python tries to look up the available attributes in the __slots__ of the class. a.abc does however still not exist, meaning that even though it is present in __slots__, a.abc is no valid object at runtime, which is why the __getattr__ fails.
This expected error is also not related to the REPL, in a plain Python script, the same error will be raised.
Yes, this topic is a little confusing, which is why I suggested to change some error messages to better reflect that.
Which is due to the list not only containing valid strings (perhaps the Error message could be improved here too?) ↩︎
To be clear, “__dir__” directly won’t sort the result while dir() will. It is a difference. So at first, the dir() failed but “__dir__” not, so the result must be in the sorting. Then it change, both dir() and “__dir__” failed.
You still don’t explicitly say what you want to propose, we have to deduce it from the session you show.
My interpretation: You propose that the error from calling dir in traceback._compute_suggestion_error is not silenced, but turned into addition information from the user (e.g. tell that ‘dir(obj)’ failed and why.
This is code I’m unfamiliar with, but the implementation seems to want to deal with issues like this, but does by ignoring the result of dir() and calculating something similar by hand (looking at the __dict__ of the object and its class).
It might be useful to introduce a level between that, e.g.:
try:
d = dir(obj)
except TypeError: # Attributes are unsortable, e.g. int and str
try:
d = obj.__dir__(). # <-- this bit is not in traceback.py
except TypeError:
d = list(obj.__class__.__dict__.keys()) + list(obj.__dict__.keys())
I haven’t thought enough about this if keeping the introspection of the class and instance __dict__ as a fallback would be useful.
In any case, this would still fail to give a suggestion if __dir__ raises some other exception. That’s IMHO not useful to try to work around, in the end the suggestion is a hint to the user and not more than that. Showing addition information as in your examples assumes that the user is in a position to fix the issue and they may not be (e.g. due to a bug in a 3th-party library)
This PR has two required PR: gh-139933 (for change the logic in suggestion) and gh-135660 (for unraisable in traceback.py)
Now gh-139933 try to fix it. Then I may change it more (type object cannot use this way, so you can see that in the final is d = obj.__dir__() if not isinstance(obj, type) else type(obj).__dir__(obj))
Here may be the final code:
It helps users to open an issue in the 3th-party library homepage, even though they cannot fix it, they can inform the writer (or the team) of the library.
class MyClass:
__slots__ = ("ab1", "ab2")
a = MyClass()
a.ab1
In the original suggesting, it will suggest “ab2”, however, it shouldn’t be given because that the list of all of the attributes is untrustworthy (user declared that there would be some attributes in the “__slots__” but didn’t set them in initialization). Now it only says that there is something wrong in the code that need to check.