Is __init__.py not required for packages in Python 3?
我使用的是python 3.5.1。我在这里阅读了文档和包部分:https://docs.python.org/3/tutorial/modules.html packages
现在,我有以下结构:
1
| /home/wujek/Playground/a/b/module.py |
module.py:
1 2 3
| class Foo:
def __init__(self):
print('initializing Foo') |
现在,在/home/wujek/Playground中:
1 2 3 4
| ~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo |
同样,现在在家里,Playground的超级文件夹:
1 2 3 4
| ~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo |
实际上,我可以做各种事情:
1 2 3 4
| ~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b |
为什么会这样?我认为当python路径指向Playground文件夹时,a和b中都需要有__init__.py文件(空文件可以),以便module.py可以导入?
这似乎与Python2.7有所不同:
1 2 3 4 5 6 7
| ~ $ PYTHONPATH=Playground python
>>> import a
ImportError: No module named a
>>> import a.b
ImportError: No module named a.b
>>> import a.b.module
ImportError: No module named a.b.module |
在~/Playground/a和~/Playground/a/b中,__init__.py都可以正常工作。
python 3.3+具有隐式名称空间包,允许它创建不带__init__.py文件的包。
Allowing implicit namespace packages means that the requirement to provide an __init__.py file can be dropped completely, and affected ... .
使用__init__.py文件的旧方法仍然可以像在python 2中那样工作。
- 我会看文件,但有点长。是否可以快速总结?你能告诉我:它还是支持init.py,还是完全忽略它们?如果它确实支持它们,那么功能上的区别是什么,为什么是二元性?
- 是的,它仍然有效。因此,所有带有__init__.py文件的python 2包都可以在导入方面工作(这里不考虑python 2和3之间的其他区别)。
- 所以教程应该更新。是否为其打开了文档错误?
- 我还是很不安,因为这违背了Zen Of Python行2:Explicit is better than implicit.……
- @但是:"尽管实用性胜过纯洁性。"
- @在我看来,这更为明确。有时它在__init__.py中执行in it操作,有时不执行。在python 3中,当我需要这些东西时,我用特定的代码创建了一个新的__init__.py,否则我就不需要了。这很容易从视觉上了解哪些包具有自定义in i t。相反,在python 2中,我总是需要放置一个__init__.py(通常是空的),这样会产生大量的EDOCX1,最后很难记住您将init代码放在哪里。这也应该符合"应该有一种——最好只有一种——显而易见的方法来做到这一点"。
- @米基姆&252;勒&@保罗,这就是为什么我喜欢埃多克斯1(6),向最好的人学习!我现在更好地理解为什么这是一件好事,恢复我以前的陈述。=)感谢您的洞察力!
- 在python 3中,是否使用了__init__.py?
- 是的,有几种用途。其中一个将"扁平化名称空间",即从子包导入模块,使其直接在包下可用。例如numpy github.com/numpy/numpy/blob/master/numpy/uuuinit_uuy.py这里from .core import *从core导入所有名称,它们可以通过numpy.name访问,其中'name'实际上位于'numpy.core'中。
重要的
@迈克的回答是正确的,但太不精确了。确实,python 3.3+支持隐式名称空间包,允许它创建不带__init__.py文件的包。
但是,这只适用于空的__init__.py文件。因此,空的__init__.py文件不再是必需的,可以省略。如果要在导入包或其任何模块或子包时运行特定的初始化脚本,您仍然需要一个__init__.py文件。这是一个很好的堆栈溢出答案,可以解释为什么您希望使用__init__.py文件进行进一步的初始化,以防您想知道为什么这在任何方面都有用。
目录结构示例:
1 2 3 4 5 6 7
| parent_package/
__init__.py <- EMPTY, NOT NECESSARY in Python 3.3+
child_package/
__init__.py <- STILL REQUIRED if you want to run an initialization script
child1.py
child2.py
child3.py |
parent_package/child_package/__init__.py:
实例
下面的示例演示在导入child_package或其某个模块时如何执行初始化脚本。
例1:
1
| from parent_package import child_package # prints"from parent" |
例2:
1
| from parent_package.child_package import child1 # prints"from parent" |
- 假设我把run_script.py和parent_package放在同一个目录下,那么我可以像from parent_package.child_package import child1一样不带__init__.py导入吗?
- 这样做的目的是为了编写child_package.some_函数,即使childx.py中定义了某个_函数?换句话说,它避免了要求用户了解child_包中的不同文件??
- 是的,我不明白你为什么要让child1.py,child2.py,而不是直接把它们的代码放在__init__py中。
- __init__中的进口报表不是相对进口,即from . import child1吗?绝对导入给了我ModuleNotFoundError(在python 3.6中)
- 谢谢@halberdrejoycth,我编辑了我的答案:)
我想说的是,只有在希望使用隐式名称空间包的情况下,才应该省略__init__.py。如果您不知道它的含义,那么您可能不想要它,因此您应该继续使用__init__.py,即使在python 3中也是如此。