On Fri, Aug 21, 2020 at 09:35:14AM -0000, Gustav O wrote:
If a file named "tkinter.py" is created and tkinter is imported and used within the file, the following exception is raised: "AttributeError: partially initialized module 'tkinter' has no attribute 'Tk' (most likely due to a circular import)"
I've spoken to multiple beginners who got stuck on this and just couldn't figure out what was happening.
Alas, I think that this is an error that won't be obvious to a beginner no matter how we word it.
* It's unusual enough that googling for the error message comes up with lots of false positives and few correct hits.
(I couldn't find anything relevant in the first half dozen results when using DuckDuckGo, although Google's first result gave the correct solution but the wrong error message!)
* The concept of a "partially initialized module" requires a pretty sophisticated understanding of the difference between a module "spam.py" as a source file and a module `spam` initialised in memory.
* It requires an understanding of circular imports and how they can go wrong.
It's also tricky to word the error message in a way that leads beginners to a solution without hiding information or being misleading in other cases. The *actual error* here is that the imported module tkinter doesn't have a Tk attribute -- everything else is a guess as to what the problem *might* be:
- a module importing itself is not necessarily wrong;
- not all circular imports are modules importing themselves;
- loading a partially imported module is a normal consequence of circular imports;
- a module not containing an attribute doesn't necessarily mean you have shadowed the real module, it might just mean a typo or bug in your code.
The other factor is that *beginners don't read error messages*.
Obviously there are exceptions, but beginners tend to be really, really bad at reading error messages even when the messages are clear, succint, to the point, and tell them exactly what is wrong. So I'm reluctant to spend to much time or energy trying to craft the perfect error message to help beginners given that the ones who most need the help are the least likely to read it.
Debugging code is a skill and there really is no substitute for time and experience to learn it. One of those lessons is first to learn that you must read the error message and second how to interpret it.
Having said all that, I cannot help but feel that shadowing of modules is such an issue that maybe we need to make a special case of this. Not specifically tkinter, of course, but if a module attempts to directly import a module with the same name, and that import fails for any reason, we should include a message about shadowing in addition to the normal exception traceback.
I think the following would be an option: "ImportError: partially initialized module 'tkinter' can't import itself"
That's a regression. In this specific case it doesn't matter because you know that the error actually is shadowing (the user named their own file "tkinter.py") but in the general case we lose the information of what name was being looked up:
AttributeError: partially initialized module 'spam' has no attribute 'egsg' (most likely due to a circular import)
If the error wasn't due to shadowing or a circular import, then knowing that I had misspelled 'eggs' would be very useful.