Ответ 1
Опоздал на вечеринку, но никогда не повредит помочь попутчикам по пути к пространству имен в Python!
# 1:
С init.py, какой из них мне следует использовать (если есть)?:
Зависит от того, что есть три способа сделать пакеты пространства имен, как указано здесь:
Используйте собственные пакеты пространства имен. Этот тип пакета пространства имен определен в PEP 420 и доступен в Python 3.3 и более поздних версиях. Это рекомендуется, если пакеты в вашем пространстве имен только когда-либо должны поддерживать Python 3 и установку через pip.
Используйте пакеты пространства имен в стиле pkgutil. Это рекомендуется для новых пакетов, которые должны поддерживать Python 2 и 3, и установки через установку pip и python setup.py.
Используйте пакеты пространства имен в стиле pkg_resources. Этот метод рекомендуется, если вам нужна совместимость с пакетами, уже использующими этот метод, или если ваш пакет должен быть zip-safe.
Если вы используете # 2 (pkgutil-style
) или # 3 (pkg_resources-style
), то вам придется использовать соответствующий стиль для файлов __init__.py
. Если вы используете собственные пространства имен, то в каталоге пространств имен нет __init__.py
.
# 2:
С setup.py, мне все еще нужно добавить параметр namespace_modules, и если да, буду ли я использовать namespace_modules = ['org.common'] или namespace_modules = ['org', 'common']?
Если выбранный вами пакет пространства имен не является собственным стилем, то да, вам понадобится namespace_packages
в вашем setup()
.
# 3:
Могу ли я отказаться от всего вышеперечисленного, просто реализовав это иначе? Возможно, что-то более простое или более "питоническое"?
Поскольку вы остановились на полной теме в python, кажется, вы знаете, что делаете, чего хотите, и определили, что создание пакета пространства имен Python - это способ сделать это. Это будет считаться питонским способом решения проблемы.
В дополнение к вашим вопросам вот несколько вещей, которые я обнаружил:
Я прочитал PEP420, Руководство по упаковке Python, и потратил много времени на понимание пакетов пространства имен, и в целом я понял, как это работает. Я прочитал пару ответов здесь, здесь, здесь, а также этот ответ на Кару. Пример здесь и по ссылке Git, опубликованной Робом.
Однако моя проблема была после того, как я создал свой пакет. Поскольку все инструкции и примеры кода явно перечисляли пакет в функции setuptools.setup(package=[])
, мой код не удался. Мои подпакеты/каталоги не были включены. Углубившись вглубь, я обнаружил, что в setuptools есть функция find_namespace_package()
, которая также помогает добавлять подпакеты
РЕДАКТИРОВАТЬ:
Ссылка на find_namespace_packages()
(версия setuptools
больше, чем 40.1.0
): https://setuptools.readthedocs.io/en/latest/setuptools.html#find-namespace-packages
ОБНОВЛЕНИЕ (08/09/2019):
Чтобы завершить ответ, позвольте мне также привести пример с реструктуризацией.
Следующее решение предполагает использование Python 3. 3+, который поддерживает неявные пакеты пространства имен
Поскольку вы ищете решение для версии Python 3.5
или более поздней, давайте возьмем предоставленные примеры кода и уточним.
Давайте предположим следующее:
Имя пакета/имя пакета Python: org
Дистрибутивные пакеты: org_client
, org_common
Python: 3.3+
setuptools: 40.1.0
Для вас сделать следующее
from org.client.client1 import mod1
from org.common import config
И ваши каталоги высшего уровня остаются прежними, а именно. org_client_client1_mod1
и org_common_config
, вы можете изменить свою структуру следующим образом
Репозиторий 1:
org_client_client1_mod1/
setup.py
org/
client/
client1/
__init__.py
submod1/
__init__.py
mod1/
__init__.py
somefile.py
file1.py
Обновлено setup.py
from setuptools import find_namespace_packages, setup
setup(
name="org_client",
...
packages=find_namespace_packages(), # Follows similar lookup as find_packages()
...
)
Хранилище 2:
org_common_config/
setup.py
org/
common/
__init__.py
config/
__init__.py
someotherfile.py
Обновлено setup.py
:
from setuptools import find_namespace_packages, setup
setup(
name="org_common",
...
packages=find_namespace_packages(), # Follows similar lookup as find_packages()
...
)
Для установки (используя pip
):
(venv) $ pip3 install org_common_config/
(venv) $ pip3 install org_client_client1_mod1/
Обновленный список пипсов покажет следующее:
(venv) $ pip3 list
...
org_client
org_common
...
Но они не будут импортироваться, чтобы импортировать, вам нужно следовать указаниям org.client
и org.common
.
Чтобы понять почему, вы можете просмотреть здесь (при условии, что внутри venv):
(venv) $ cd venv/lib/python3.5/site-packages/
(venv) $ ls -l | grep org
Вы увидите, что там нет каталогов org_client
или org_common
, они интерпретируются как пакет пространства имен.
(venv) $ cd venv/lib/python3.5/site-packages/org/
(venv) $ ls -l
client/
common/
...