Является __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>
Аналогично, теперь в home
, суперпапке 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
Обзор
Ответ @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/
. Это должен быть единственный вариант использования для создания пакетов пространства имен, в противном случае в нем нет необходимости.
Крайне важно, чтобы в каталогах __init__py
и google
не было google/cloud
файлов, чтобы оба каталога можно было интерпретировать как пакеты пространства имен. В Python 3.3+ любой каталог в sys.path
с именем, совпадающим с именем искомого пакета, будет распознан как добавляющие модули и подпакеты к этому пакету. В результате, когда вы импортируете оба из google_pubsub
и google_storage
, интерпретатор Python сможет их найти.
Это отличается от обычных пакетов, которые являются автономными, что означает, что все части находятся в одной иерархии каталогов. При импорте пакета интерпретатор Python обнаруживает подкаталог в sys.path
с __init__.py
файлом, тогда он создаст пакет с одним каталогом, содержащий только модули из этого каталога, вместо того, чтобы находить все подкаталоги с соответствующими именами за пределами этого каталога. Это прекрасно подходит для пакетов, которые не хотят совместно использовать пространство имен. Я настоятельно рекомендую взглянуть на ловушки для неосторожных в системе импорта Python, чтобы лучше понять, как импорт Python работает с обычным пакетом и пакетом пространства имен и каких __init__.py
ловушек следует остерегаться.
Краткие сведения
- Пропускайте
__init__.py
файлы только в том случае, если вы хотите создать пакеты пространства имен. Создавайте пакеты namespace только в том случае, если у вас есть разные библиотеки, которые находятся в разных расположениях, и вы хотите, чтобы каждая из них добавляла подпакет в родительский пакет, то есть пакет namespace. - Продолжайте добавлять empty
__init__.py
в свои каталоги, потому что в 99% случаев вы просто хотите создавать обычные пакеты. Кроме того, существующие инструменты Python, такие какmypy
иpytest
требуют пустых__init__.py
файлов для соответствующей интерпретации структуры кода. Это может привести к странным ошибкам, если не выполнять их с осторожностью.
Ресурсы
Мой ответ касается только того, как работают обычные пакеты и пакеты пространств имен, поэтому взгляните на следующие ресурсы для получения дополнительной информации:
Ответ 2
В Python 3.3+ есть неявные пространства имен Packages, которые позволяют создавать пакеты без __init__.py
файла.
Разрешение неявных пакетов пространства имен означает, что требование о предоставлении
__init__.py
файла может быть полностью отменено и затронуто ... .
Старый способ с __init__.py
файлами по-прежнему работает как в Python 2.
Ответ 3
Если у вас есть setup.py
в вашем проекте и вы используете find_packages()
внутри него, необходимо иметь __init__.py
файл в каждом каталоге, чтобы пакеты находились автоматически.
Пакеты распознаются только в том случае, если они включают
__init__.py
файл
UPD: если вы хотите использовать неявные пакеты пространства имен без __init__.py
вам просто нужно использовать find_namespace_packages()
вместо этого
Ответ 4
Я бы сказал, что следует опустить __init__.py
только если вы хотите иметь неявный пакет пространства имен. Если вы не знаете, что это значит, вам, вероятно, это не нужно, и поэтому вам следует продолжать использовать __init__.py
даже в Python 3.