Из того, что я понял из чтения PEP 420 , начиная с python3 .3 пустых __init__.py
файлов, больше нет необходимости превращать каталоги в python пакеты. если __init__.py
опущен, пакет считается пакетом пространства имен. Кроме того, пакеты пространства имен должны вести себя так же, как и обычные пакеты. Из PEP
Пакет пространства имен принципиально не отличается от обычного пакета. Это просто другой способ создания пакетов. После создания пакета пространства имен между ним и обычным пакетом нет никакой функциональной разницы.
Однако порядок, в котором ищутся пакеты, кажется, совершенно различен для двух типов пакетов. Для обычных пакетов текущий рабочий каталог, кажется, ищется перед установочными каталогами, в то время как для пакетов пространства имен обратное верно. Это предполагаемое поведение? Кажется, я не могу найти упоминаний об этом в PEP или в других источниках.
Пример
Например, попробуйте выполнить следующее из пустой директории. Он импортирует установленный модуль pytest
.
$ tree
.
0 directories, 0 files
$ python3.7
>>> import pytest
>>> print(pytest.__file__)
/opt/lib/python3.7/site-packages/pytest.py
Теперь создайте файл с именем pytest.py в каталоге и снова запустите его. Он импортирует ожидаемый локальный пакет.
$ tree
.
`-- pytest.py
0 directories, 1 file
$ python3.7
>>> import pytest
>>> print(pytest.__file__)
/home/cnoor/ns_package_test/pytest.py
Теперь удалите файл pytest.py и создайте каталог с именем pytest. Импортирует установленный пакет вместо локального. Почему?
$ tree
.
`-- pytest/
1 directory, 0 files
$ python3.7
>>> import pytest
>>> print(pytest.__file__)
/opt/lib/python3.7/site-packages/pytest.py
теперь попробуйте добавить пустой файл __init__.py
в каталог pytest. Он снова импортирует локальный.
$ tree
.
`-- pytest/
`-- __init__.py
1 directory, 1 file
$ python3.7
>>> import pytest
>>> print(pytest.__file__)
/home/cnoor/ns_package_test/pytest/__init__.py
Может кто-нибудь объяснить, что происходит? Я знаю, что импорт пустых пакетов - не самая полезная вещь в мире, но ситуация применима, даже если в пакете есть субмодули или субпакеты.