Почему это работает? Я думал, что должны быть __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
Обзор
Ответ @Mike правильный, но слишком неточный. Это правда, что Python 3.3 + поддерживает неявные пакеты пространства имен, что позволяет создавать пакет без __init__.py файла. Это называется пакетом пространства имен в отличие от обычного пакета, в котором есть __init__.py файл (пустой или не пустой).
Однако создавать пакет пространства имен следует ТОЛЬКО в том случае, если в этом есть необходимость. Для большинства вариантов использования и для разработчиков это неприменимо, поэтому вы должны придерживаться ПУСТЫХ __init__.py файлов в любом случае.
Пример использования пакета Namespace
Чтобы продемонстрировать разницу между двумя типами пакетов python, давайте посмотрим на следующий пример:
google_pubsub/ <- Package 1 google/ <- Namespace package (there is no __init__.py) cloud/ <- Namespace package (there is no __init__.py) pubsub/ <- Regular package (with __init__.py) __init__.py <- Required to make the package a regular package foo.py
google_storage/ <- Package 2 google/ <- Namespace package (there is no __init__.py) cloud/ <- Namespace package (there is no __init__.py) storage/ <- Regular package (with __init__.py) __init__.py <- Required to make the package a regular package bar.py
google_pubsub и google_storage являются отдельными пакетами, но они используют одно и то же пространство имен google/cloud. Чтобы использовать одно и то же пространство имен, требуется сделать каждый каталог общего пути пакетом пространства имен, т.е. google/ и cloud/. Это должен быть единственный вариант использования для создания пакетов пространства имен, в противном случае в нем нет необходимости.
Это отличается от обычных пакетов, которые являются автономными, что означает, что все части находятся в одной иерархии каталогов. При импорте пакета интерпретатор Python обнаруживает подкаталог в sys.path с __init__.py файлом, тогда он создаст пакет с одним каталогом, содержащий только модули из этого каталога, вместо того, чтобы находить все подкаталоги с соответствующими именами за пределами этого каталога. Это прекрасно подходит для пакетов, которые не хотят совместно использовать пространство имен. Я настоятельно рекомендую взглянуть на ловушки для неосторожных в системе импорта Python, чтобы лучше понять, как импорт Python работает с обычным пакетом и пакетом пространства имен и каких __init__.py ловушек следует остерегаться.
Краткие сведения
Пропускайте __init__.py файлы только в том случае, если вы хотите создать пакеты пространства имен. Создавайте пакеты namespace только в том случае, если у вас есть разные библиотеки, которые находятся в разных расположениях, и вы хотите, чтобы каждая из них добавляла подпакет в родительский пакет, то есть пакет namespace.
Продолжайте добавлять empty __init__.py в свои каталоги, потому что в 99% случаев вы просто хотите создавать обычные пакеты. Кроме того, существующие инструменты Python, такие как mypy и pytest требуют пустых __init__.py файлов для соответствующей интерпретации структуры кода. Это может привести к странным ошибкам, если не выполнять их с осторожностью.
Ресурсы
Мой ответ касается только того, как работают обычные пакеты и пакеты пространств имен, поэтому взгляните на следующие ресурсы для получения дополнительной информации:
Разрешение неявных пакетов пространства имен означает, что требование о предоставлении __init__.py файла может быть полностью отменено и затронуто ... .
Старый способ с __init__.py файлами по-прежнему работает как в Python 2.
Ответ 3
Если у вас есть setup.py в вашем проекте и вы используете find_packages() внутри него, необходимо иметь __init__.py файл в каждом каталоге, чтобы пакеты находились автоматически.
Пакеты распознаются только в том случае, если они включают __init__.py файл
UPD: если вы хотите использовать неявные пакеты пространства имен без __init__.py вам просто нужно использовать find_namespace_packages() вместо этого
Я бы сказал, что следует опустить __init__.py только если вы хотите иметь неявный пакет пространства имен. Если вы не знаете, что это значит, вам, вероятно, это не нужно, и поэтому вам следует продолжать использовать __init__.py даже в Python 3.