问题:Python 3.3+中的软件包不需要__init__.py吗
我正在使用Python 3.5.1。我在这里阅读了文档和包部分:https : //docs.python.org/3/tutorial/modules.html#packages
现在,我具有以下结构:
/home/wujek/Playground/a/b/module.py
module.py
:
class Foo:
def __init__(self):
print('initializing Foo')
现在,在/home/wujek/Playground
:
~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x100a8f0b8>
同样,现在在家里,超级文件夹Playground
:
~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x10a5fee10>
实际上,我可以做各种事情:
~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b
为什么这样做?我虽然__init__.py
两者都需要文件(空文件可以工作),a
并且b
要module.py
在Python路径指向Playground
文件夹时可导入?
这似乎与Python 2.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
随着__init__.py
在这两个~/Playground/a
和~/Playground/a/b
它工作正常。
回答 0
Python 3.3+具有隐式命名空间包,允许它创建不带__init__.py
文件的包。
允许隐式命名空间包意味着可以完全放弃提供
__init__.py
文件的要求,并使其受到影响。
__init__.py
文件的旧方法仍然可以在Python 2中使用。
回答 1
重要
@Mike的回答是正确的,但过于精确。确实,Python 3.3+支持隐式命名空间包,这允许它创建不带__init__.py
文件的包。
但是,这仅适用于EMPTY__init__.py
文件。因此,EMPTY__init__.py
文件不再是必需的,可以省略。如果要在导入软件包或其任何模块或子软件包时运行特定的初始化脚本,则仍然需要__init__.py
文件。这是一个很好的Stack Overflow答案,它说明了为什么您想使用__init__.py
文件进行一些进一步的初始化,以防您想知道为什么这样做有任何用处。
目录结构示例:
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
:
print("from parent")
例子
以下示例演示了如何在执行初始化脚本时执行初始化脚本。 child_package
导入或其中一个模块。
范例1:
from parent_package import child_package # prints "from parent"
范例2:
from parent_package.child_package import child1 # prints "from parent"
回答 2
如果你有 setup.py
在项目中并在其中使用find_packages()
,则必须__init__.py
在每个目录中都有一个文件,以便自动找到软件包。
程序包仅在包含
__init__.py
文件的情况下才被识别
UPD:如果你想使用隐式命名空间包,而__init__.py
你只需要使用find_namespace_packages()
替代
回答 3
我要说的是,__init__.py
只有一个人想要拥有隐式命名空间包时,才应该省略它。如果您不知道这意味着什么,则可能不想要它,因此您应该__init__.py
在Python 3中继续使用even。