使用__init__.py导入Python子模块

时间:2014-06-19 09:04:08

标签: python

我正在学习Python,而我无法弄清楚__init__.py中的导入是如何工作的。

我从the Python tutorial了解到__init__.py文件初始化了一个包,并且我可以在这里导入子包。

但是,我做错了。你能为我(以及未来的Python学习者)解释我做错了什么吗?

以下是我尝试做的简单示例。

这是我的文件结构:

package
    __init__.py
    test.py
    subpackage
        __init__.py
        hello_world.py

hello_world.py的内容:

def do_something():
    print "Hello, world!"

subpackage/__init__.py为空。

package/__init__.py包含:

import test.submodule.do_something

最后,test.py包含:

do_something()

这是我尝试使用OSX终端和Python 3运行hello_world.py的方式:

python test.py
然后,Python会抛出以下错误:

NameError: name 'do_something' is not defined

3 个答案:

答案 0 :(得分:17)

您可能已经明白,当您导入模块时,解释器会创建一个新的命名空间,并使用新的命名空间作为本地命名空间和全局命名空间来执行该模块的代码。当代码完成执行时,模块名称(或任何as子句中给出的名称)绑定到刚刚在导入名称空间中创建的模块对象,并根据__name__中的sys.modules进行记录

当导入限定名称(例如package.subpackage.module)时,会将第一个名称(package)导入到本地名称空间,然后将subpackage导入package的名称空间最后将module导入package.subpackage的命名空间。使用from ... import ... as ...的导入执行相同的操作序列,但导入的对象直接绑定到导入模块的命名空间中的名称。包名称未绑定在本地名称空间中的事实并不意味着它尚未导入(因为sys.modules的检查将显示)。

包中的__init__.py与模块的.py文件具有相同的功能。具有结构的被编写为目录,该目录还可以包含任何子包的模块(常规.py文件)和子目录(也包含__init__.py文件)。导入包时,将创建一个新的命名空间,并使用该命名空间作为本地和全局命名空间执行包__init__.py。因此,为了回答您的问题,我们可以通过省略顶级软件包来删除文件存储区,当test.py作为程序运行时,解释器将永远不会考虑该软件包。它看起来像这样:

test.py
subpackage/
    __init__.py
    hello_world.py

现在,subpackage不再是子包,因为我们已将包含的包删除为无关紧要。关注do_something名称未定义的原因可能会有所帮助。 test.py不包含任何导入,因此不清楚您期望do_something获得意义的方式。您可以使用空subpackage/__init__.py然后test.py读取

来使其工作
from subpackage.hello_world import do_something
do_something()

另外,您可以使用subpackage/__init__.py来读取

from hello_world import do_something

在导入包时在do_something命名空间内建立subpackage函数。然后使用从包中导入函数的test.py,如下所示:

from subpackage import do_something
do_something()

具有相同__init__.py的最终替代方法是使用仅导入(子)包的test.py,然后使用相对命名来访问所需的函数:

import subpackage
subpackage.do_something()

在本地命名空间中访问它

__init__.py这也可以通过test.py阅读

来实现
import subpackage.hello_world
subpackage.hello_world.do_something()

甚至

from subpackage.hello_world import do_something
do_something()

最终,让您保持领先的最佳工具是清楚地了解导入的工作原理以及其各种形式对导入命名空间的影响。

答案 1 :(得分:1)

首先,您必须了解import单独工作的方式:

import test.submodule.do_something

尝试从do_something加载的submodule加载test

你想从subpackage加载一些东西,所以从那开始:

import subpackage

很好,subpackage/__init__.py已加载。

现在,您需要文件中的do_something()函数("模块")hello_world.py。易:

from subpackage.hello_world import do_something

你完成了!只需大声读取此行,它就会完全按照其说明:从do_something包中的模块hello_world导入subpackage

test.py

中试试
from subpackage.hello_world import do_something

do_something()

它应该可以正常工作。

现在,第二个问题:

由于您未使用__init__.py作为套餐,因此package/无法调用{p> package/。如果您导入__init__.py或其中的任何内容,将使用package/,例如:

from package import test

否则,它根本不会被加载。

但是,如果您要在导入子包时加载do_something(),请将from submodule.hello_word import do_something放入subpackage/__init__.py,然后在test.py中,执行{{1} }}

答案 2 :(得分:1)

在Python中,这是一个绝对的硬性规则,必须始终在您正在使用它的模块中定义或导入名称。在这里,你永远不会在test.py中导入任何内容 - 因此,如错误所示,do_something未定义。

即使您的package/__init__.py文件已被执行(正如其他人所指出的那样,但事实并非如此),您的代码仍然无法正常工作,因为导入do_something已经如果要在该文件中引用它,可以在test.py中完成。