<p>您可能已经理解了,当导入<em>模块</em>时,解释器将创建一个新的名称空间,并使用新名称空间作为本地和全局名称空间来执行该模块的代码。当代码完成执行时,模块名(或任何<code>as</code>子句中给定的名称)将绑定到刚在导入命名空间中创建并记录在其<code>sys.modules</code>中的<code>__name__</code>中的模块对象。</p>
<p>当一个限定名(如<code>package.subpackage.module</code>)被导入时,第一个名(<code>package</code>)被导入本地命名空间,然后<code>subpackage</code>被导入<code>package</code>的命名空间,最后<code>module</code>被导入<code>package.subpackage</code>的命名空间。使用<code>from ... import ... as ...</code>的导入执行相同的操作序列,但导入的对象直接绑定到导入模块命名空间中的名称。包名没有绑定在本地命名空间中并不意味着它没有被导入(正如对<code>sys.modules</code>的检查将显示的那样)。</p>
<p>包中的<code>__init__.py</code>与模块的<code>.py</code>文件的功能几乎相同。具有结构的<em>包</em>被编写为一个目录,该目录还可以包含任何子包的模块(常规<code>.py</code>文件)和子目录(也包含<code>__init__.py</code>文件)。导入包时,将创建一个新的命名空间,并使用该命名空间作为本地和全局命名空间来执行包的<code>__init__.py</code>。因此,为了解决您的问题,我们可以通过省略顶级包来删除您的文件存储,当<code>test.py</code>作为程序运行时,解释器永远不会考虑这个顶级包。然后看起来像这样:</p>
<pre><code>test.py
subpackage/
__init__.py
hello_world.py
</code></pre>
<p>现在,<code>subpackage</code>不再是子包,因为我们已经删除了不相关的包含包。关注<code>do_something</code>名称未定义的原因可能会有所帮助。<code>test.py</code>不包含任何导入,因此不清楚您期望<code>do_something</code>如何获得意义。您可以使用空的<code>subpackage/__init__.py</code>使其工作,然后<code>test.py</code>可以读取</p>
<pre><code>from subpackage.hello_world import do_something
do_something()
</code></pre>
<p>或者你可以给我们一个<code>subpackage/__init__.py</code>,上面写着</p>
<pre><code>from hello_world import do_something
</code></pre>
<p>它在导入包时在<code>subpackage</code>命名空间内建立<code>do_something</code>函数。然后使用从包中导入函数的<code>test.py</code>,如下所示:</p>
<pre><code>from subpackage import do_something
do_something()
</code></pre>
<p>使用相同<code>__init__.py</code>的最后一种方法是使用<code>test.py</code>,该方法只需导入(子)包,然后使用相对命名来访问所需的函数:</p>
<pre><code>import subpackage
subpackage.do_something()
</code></pre>
<p>在本地命名空间中访问它</p>
<p>空的<code>__init__.py</code>也可以通过读取<code>test.py</code>来实现</p>
<pre><code>import subpackage.hello_world
subpackage.hello_world.do_something()
</code></pre>
<p>甚至</p>
<pre><code>from subpackage.hello_world import do_something
do_something()
</code></pre>
<p>归根结底,最好的工具是清楚地了解import是如何工作的,以及它的各种形式对导入名称空间有什么影响。</p>