使用初始化Python子模块导入

2024-05-15 00:40:43 发布

您现在位置: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终端和Python3运行hello_world.py:

python test.py

然后,Python抛出以下错误:

NameError: name 'do_something' is not defined

Tags: 文件thepytestpackagehelloworldinit
3条回答

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

import test.submodule.do_something

试图从submodule加载do_something本身从test加载。

你想从subpackage加载一些内容,那么从这个开始:

import subpackage

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

现在,您需要文件中的do_something()函数(一个“模块”)hello_world.py。简单:

from subpackage.hello_world import do_something

你完了!只要大声读这一行,它就会按它所说的做:从subpackage包中的模块hello_world导入do_something

test.py中尝试

from subpackage.hello_world import do_something

do_something()

它应该工作得很好。

现在,第二期:

__init__.py不会在package/中调用,因为您不使用package/作为包。__init__.py将用于导入package/或其中的任何内容,例如:

from package import test

否则,它根本不会加载。

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

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

当一个限定名(如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

它在导入包时在subpackage命名空间内建立do_something函数。然后使用从包中导入函数的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()

归根结底,最好的工具是清楚地了解import是如何工作的,以及它的各种形式对导入名称空间有什么影响。

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

即使您的package/__init__.py文件已被执行(正如其他人指出的那样,它没有执行),您的代码仍然无法正常工作,因为如果要在该文件中引用do_something的导入必须在test.py中完成。

相关问题 更多 >

    热门问题