__Init__.py не требуется для пакетов в Python 3.3+

Я использую 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 он отлично работает.

Ответы

Ответ 1

Python 3. 3+ имеет неявные пакеты пространства имен, которые позволяют ему создавать пакеты без файла __init__.py.

Разрешение неявных пакетов пространства имен означает, что требование предоставить файл __init__.py может быть полностью отброшено и затронуто....

Старый способ с файлами __init__.py прежнему работает как в Python 2.

Ответ 2

ВАЖНЫЙ

@Майк ответ правильный, но слишком неточный. Это правда, что Python 3. 3+ поддерживает неявные пакеты пространства имен, что позволяет ему создавать пакет без файла __init__.py.

Это, однако, относится ТОЛЬКО к файлам EMPTY __init__.py. Таким образом, файлы EMPTY __init__.py больше не нужны и могут быть опущены. Если вы хотите запустить определенный сценарий инициализации при импорте пакета или любого из его модулей или подпакетов, вам все равно требуется файл __init__.py. Это отличный ответ о переполнении стека, почему вы захотите использовать файл __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"

Ответ 3

Если у вас есть setup.py в вашем проекте и вы используете find_packages() внутри него, необходимо иметь файл __init__.py в каждом каталоге для автоматического поиска пакетов.

Пакеты распознаются, только если они содержат файл __init__.py

Документы

Ответ 4

Я бы сказал, что __init__.py следует опускать, только если вы хотите иметь неявный пакет пространства имен. Если вы не знаете, что это значит, вы, вероятно, не хотите этого, и поэтому вам следует продолжать использовать __init__.py даже в Python 3.