Why Tkinter Module Raises Attribute Error When Run Via Command Line But Not When Run Via Idle?
Solution 1:
I want to start by saying: always explicitly import submodules if you know you will use them. The end of this answer has a more compelling case where this is important.
Because of the structure of tkinter
you must explicitly import submodules for them to load:
import tkinter as tk
print(hasattr(tk,"filedialog")) # in a standard interpreter will print falseimport tkinter.filedialog
print(hasattr(tk,"filedialog")) # should always print true after explicit import
the reason you don't need to do this in IDLE is that before your code is run IDLE sets up some stuff in the background and ends up importing some of the tkinter libraries. One of the maintainers has commented that this is effectively a bug in IDLE.
In python 3.6.5 (and possibly earlier, only checked this version) this specific discrepancy has been fixed so it no longer happens for all but 2 modules I show below.
in any version you can see a list of submodules that are loaded with some code like this:
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 282018, 03:03:55)
# standard interpreter >>> import sys
>>> len(sys.modules) #total number of modules automatically loaded71>>> sorted(name for name in sys.modules.keys() if ("."in name)) #submodules loaded
['collections.abc', 'encodings.aliases', 'encodings.latin_1', 'encodings.utf_8', 'importlib._bootstrap', 'importlib._bootstrap_external', 'importlib.abc', 'importlib.machinery', 'importlib.util', 'os.path']
>>> len(_) #number of submodules10
And in IDLE:
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 282018, 03:03:55)
# IDLE>>> import sys
>>> len(sys.modules)
152>>> sorted(name for name in sys.modules.keys() if ("."in name and"idlelib"notin name))
['collections.abc', 'encodings.aliases', 'encodings.ascii', 'encodings.latin_1', 'encodings.utf_8', 'importlib._bootstrap', 'importlib._bootstrap_external', 'importlib.abc', 'importlib.machinery', 'importlib.util', 'os.path', 'tkinter.constants', 'urllib.parse']
>>> len(_) #number of submodules not directly related to idlelib.13
tkinter.constants
is loaded when you just import tkinter
so as of the version I tested, this issue still exists for only urllib.parse
and encodings.ascii
(and idlelib
modules but generally production code doesn't use that)
This isn't necessarily an IDLE specific issue though, a worse issue is if the submodule is loaded by another library you use. Take the following code as an example:
>>> import pandas
>>> import http
>>> http.client
<module 'http.client'from'.../http/client.py'>
now lets say we wrote some other code that still used http.client
but didn't use pandas:
>>> import http
>>> http.client
Traceback(most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module'http' has no attribute 'client'
This way you could end up with a submodule that works properly when the code that uses it loads http.client
possibly by using a library that happens to use it but will otherwise fail.
This takes me back to my initial point - always explicitly import submodules.
Solution 2:
Actually it's true that the module has no attribute filedialog
, it's a submodule and you should import it as import tkinter.filedialog
before using it. You can use tk.filedialog
without explicitly importing filedialog
in IDLE because it's already imported.
import sys
sys.modules['tkinter.filedialog']
The above code will raise a KeyError
in a standard python interpreter but it will return something like <module 'tkinter.filedialog' from '/usr/lib/python3.5/tkinter/filedialog.py'>
in IDLE.
Post a Comment for "Why Tkinter Module Raises Attribute Error When Run Via Command Line But Not When Run Via Idle?"