<p>我想首先说:如果知道要使用子模块,请始终显式地导入它们。</p>
<p>由于<code>tkinter</code>的结构,您必须显式导入子模块才能加载:</p>
<pre><code>import tkinter as tk
print(hasattr(tk,"filedialog")) # in a standard interpreter will print false
import tkinter.filedialog
print(hasattr(tk,"filedialog")) # should always print true after explicit import
</code></pre>
<p>不需要在IDLE中执行此操作的原因是,在代码运行之前,IDLE会在后台设置一些东西,并最终导入一些tkinter库。维护人员之一<a href="https://stackoverflow.com/questions/36163561/why-tkinter-module-raises-attribute-error-when-run-via-command-line-but-not-when/36165227#comment59972152_36163561">has commented</a>认为这实际上是一个空闲的bug。</p>
<p><em>在python 3.6.5中(可能更早的版本,只检查了这个版本)<strong>这个特定的差异已经被修复了</strong>所以除了下面显示的2个模块之外,其他模块都不再发生这种情况。</em></p>
<p>在任何版本中,都可以看到加载了如下代码的子模块列表:</p>
<pre><code># standard interpreter
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 03:03:55)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> len(sys.modules) #total number of modules automatically loaded
71
>>> 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 submodules
10
</code></pre>
<p>空闲时:</p>
<pre><code>Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 03:03:55)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "copyright", "credits" or "license()" for more information.
>>> import sys
>>> len(sys.modules)
152
>>> sorted(name for name in sys.modules.keys() if ("." in name and "idlelib" not in 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
</code></pre>
<p><code>tkinter.constants</code>是在您刚刚<code>import tkinter</code>时加载的,因此在我测试的版本中,这个问题仍然只存在于<code>urllib.parse</code>和<code>encodings.ascii</code>(以及<code>idlelib</code>模块中,但通常生产代码不使用这个问题)</p>
<hr/>
<p>不过,这不一定是空闲的特定问题,更糟糕的问题是子模块是否由您使用的另一个库加载。以下面的代码为例:</p>
<pre><code>>>> import pandas
>>> import http
>>> http.client
<module 'http.client' from '.../http/client.py'>
</code></pre>
<p>现在假设我们编写了一些其他代码,它们仍然使用<code>http.client</code>,但没有使用panda:</p>
<pre><code>>>> import http
>>> http.client
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'http' has no attribute 'client'
</code></pre>
<p>这样,当使用它的代码加载<code>http.client</code>时,您就可以得到一个子模块,该子模块可以正常工作,这可能是由于使用了一个碰巧使用它但否则将失败的库。</p>
<p>这让我回到我的初始点-总是显式地导入子模块。</p>