Python 3.3+中的软件包不需要__init__.py吗

问题: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并且bmodule.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它工作正常。

I am using Python 3.5.1. I read the document and the package section here: https://docs.python.org/3/tutorial/modules.html#packages

Now, I have the following structure:

/home/wujek/Playground/a/b/module.py

module.py:

class Foo:
    def __init__(self):
        print('initializing Foo')

Now, while in /home/wujek/Playground:

~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x100a8f0b8>

Similarly, now in home, superfolder of Playground:

~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x10a5fee10>

Actually, I can do all kinds of stuff:

~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b

Why does this work? I though there needed to be __init__.py files (empty ones would work) in both a and b for module.py to be importable when the Python path points to the Playground folder?

This seems to have changed from 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

With __init__.py in both ~/Playground/a and ~/Playground/a/b it works fine.


回答 0

Python 3.3+具有隐式命名空间包,允许它创建不带__init__.py文件的包。

允许隐式命名空间包意味着可以完全放弃提供__init__.py文件的要求,并使其受到影响。

__init__.py文件的旧方法仍然可以在Python 2中使用。

Python 3.3+ has Implicit Namespace Packages that allow it to create a packages without an __init__.py file.

Allowing implicit namespace packages means that the requirement to provide an __init__.py file can be dropped completely, and affected … .

The old way with __init__.py files still works as in 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"

IMPORTANT

@Mike’s answer is correct but too imprecise. It is true that Python 3.3+ supports Implicit Namespace Packages that allows it to create a package without an __init__.py file.

This however, ONLY applies to EMPTY __init__.py files. So EMPTY __init__.py files are no longer necessary and can be omitted. If you want to run a particular initialization script when the package or any of its modules or sub-packages are imported, you still require an __init__.py file. This is a great Stack Overflow answer for why you would want to use an __init__.py file to do some further initialization in case you wondering why this is in any way useful.

Directory Structure Example:

  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")

EXAMPLES

The below examples demonstrate how the initialization script is executed when the child_package or one of its modules is imported.

Example 1:

from parent_package import child_package  # prints "from parent"

Example 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()替代

文件

If you have setup.py in your project and you use find_packages() within it, it is necessary to have an __init__.py file in every directory for packages to be automatically found.

Packages are only recognized if they include an __init__.py file

UPD: If you want to use implicit namespace packages without __init__.py you just have to use find_namespace_packages() instead

Docs


回答 3

我要说的是,__init__.py只有一个人想要拥有隐式命名空间包时,才应该省略它。如果您不知道这意味着什么,则可能不想要它,因此您应该__init__.py在Python 3中继续使用even。

I would say that one should omit the __init__.py only if one wants to have the implicit namespace package. If you don’t know what it means, you probably don’t want it and therefore you should continue to use the __init__.py even in Python 3.