Не требуется ли __init__.py для пакетов в Python 3?

Я использую Python 3.5.1. Я прочитал документ и раздел пакета здесь: https://docs.python.org/3/tutorial/modules.html

Теперь у меня есть следующая структура:

/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 это работает отлично.

2 ответа

Решение

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

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

Старый способ с __init__.py файлы все еще работают как в Python 2.

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

Однако это относится ТОЛЬКО к файлам EMPTY __init__.py. Таким образом, файлы EMPTY __init__.py больше не нужны и могут быть опущены. Если вы хотите импортировать модули в пакет, вам все равно требуется файл __init__.py, в котором перечислены все импортируемые файлы.

Пример структуры каталогов:

  parent_package/
     __init__.py            <- EMPTY, NOT NECESSARY in Python 3.3+
     child_package/
          __init__.py       <- STILL REQUIRED to import all child modules
          child1.py
          child2.py
          child3.py

__init__ файл в child_package:

import child1
import child2
import child3

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

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

Документы

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

По моему опыту, даже с python 3.3+ пустой __init__.pyвсе еще иногда требуется. Одна из ситуаций - когда вы хотите назвать подпапку пакетом. Например, когда я бежал python -m test.foo, это не сработало, пока я не создал пустой __init__.pyв тестовой папке. И я говорю о версии 3.6.6, которая появилась довольно недавно.

Кроме того, даже по причинам совместимости с существующим исходным кодом или руководящими принципами проекта, неплохо иметь пустой __init__.py в папке вашего пакета.

Другие вопросы по тегам