我正在学习 Python,但我无法弄清楚 __init__.py
中的导入是如何工作的。
我从 Python 教程 中了解到 __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
原文由 Benjamin 发布,翻译遵循 CC BY-SA 4.0 许可协议
您可能已经了解,当您导入 模块 时,解释器会创建一个新的命名空间,并使用新命名空间作为本地和全局命名空间来执行该模块的代码。当代码完成执行时,模块名称(或任何
as
子句中给出的名称)绑定到刚刚在导入命名空间中创建的模块对象,并根据其__name__
在sys.modules
。When a qualified name such as
package.subpackage.module
is imported the first name (package
) is imported into the local namespace, thensubpackage
is imported intopackage
的命名空间,最后module
导入到package.subpackage
的命名空间。使用from ... import ... as ...
的导入执行相同的操作序列,但导入的对象直接绑定到导入模块命名空间中的名称。包名称未绑定到您的本地命名空间这一事实并不意味着它尚未被导入(检查sys.modules
将显示)。包中的
__init__.py
与模块的.py
文件具有相同的功能。具有结构的 包 被编写为一个目录,该目录还可以包含任何子包的模块(常规.py
文件)和子目录(也包含__init__.py
文件)。导入包时,会创建一个新的命名空间,并使用该命名空间作为本地和全局命名空间来执行包的__init__.py
。因此,为了回答您的问题,我们可以通过省略顶级包来剥离您的文件存储,当test.py
作为程序运行时,解释器将永远不会考虑它。它看起来像这样:现在,
subpackage
不再是子包,因为我们已经删除了不相关的包含包。关注do_something
名称未定义的原因可能会有所帮助。test.py
不包含任何导入,因此不清楚您如何期望do_something
获得意义。你可以通过使用一个空的subpackage/__init__.py
让它工作,然后你会写test.py
作为或者,您可以使用
subpackage/__init__.py
读取导入包时,它会在
subpackage
命名空间中建立do_something
函数。然后使用test.py
从包中导入函数,如下所示:具有相同
__init__.py
的最终替代方案是使用test.py
只需导入(子)包,然后使用相对命名来访问所需的函数:在您的本地名称空间中访问它。
对于空的
__init__.py
这也可以通过test.py
阅读来实现甚至
一个空的
__init__.py
意味着顶级包命名空间将只包含程序导入的任何子包的名称,这允许你只导入你需要的子包。这使您可以控制顶级包的名称空间。虽然完全有可能在
__init__.py
中定义类和函数,但更正常的方法是将内容从子模块导入该命名空间,以便导入者只需导入顶级包即可访问其内容单级属性引用,甚至使用from
只导入您特别想要的名称。最终,让您保持直觉的最佳工具是清楚地了解 import 的工作原理以及它的各种形式对导入命名空间的影响。