python 3中的包是否不需要__init__.py

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文件夹时,ab中都需要有__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中那样工作。


重要的

@迈克的回答是正确的,但太不精确了。确实,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

1
print("from parent")

实例

下面的示例演示在导入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"


我想说的是,只有在希望使用隐式名称空间包的情况下,才应该省略__init__.py。如果您不知道它的含义,那么您可能不想要它,因此您应该继续使用__init__.py,即使在python 3中也是如此。