Глубоко вложенные пакеты пространства имен - PullRequest
1 голос
/ 24 сентября 2019

Мне нужно поддерживать некоторый инструмент ETL, сконструированный таким образом, чтобы задачи и конвейеры определялись как набор пакетов Python.Подумайте об архитектуре плагинов с небольшим ядром и почти тысячами плагинов во вложенных пространствах имен / пакетов / подпакетов.Это не горячий беспорядок пока , общее качество довольно хорошее, но setup.py и __init__.py -ы выглядят очень неприлично и иногда вызывают неожиданные проблемы при импорте.

Я бы хотелчтобы упростить это немного.Начиная с Python 3.3 мы можем помещать пакеты в пространства имен, просто создавая подкаталоги без __init__.py.Это именно то, что мне нужно, но я бы хотел избежать глубоко вложенных подкаталогов в исходном коде, потому что большое количество пакетов очень мало.В крайнем случае они выглядели бы так:

$ tree
.
├── setup.cfg
├── setup.py
└── src
    └── foo
        └── bar
            └── baz
                └── xyz
                    └── uvw
                        └── package
                            ├── actual_code.py
                            └── __init__.py

Есть ли способ использовать неявные пространства имен без такой глубокой структуры и просто указать пространство имен где-нибудь в setup.py (или даже лучше setup.cfg)?Другими словами, существует ли простой способ сказать: установить package в foo.bar.baz.xyz.uvw пространстве имен?

Я хотел бы иметь такую ​​структуру:

$ tree
.
├── setup.cfg
├── setup.py
└── src
    └── package
        ├── actual_code.py
        └── __init__.py

но процесс установки должен поместить package в папку foo/bar/baz/xyz/uvw/package, чтобы ее можно было импортировать с полным путем.

Редактировать: Это даже хорошая идея?

1 Ответ

2 голосов
/ 24 сентября 2019

Это возможно, используя аргумент package_dir для distutils.core.setup (или эквивалент setuptools).

Просто измените ваш setup.py, чтобы он содержал что-то вроде:

from distutils.core import setup

setup(# ... other setup arguments ...
      package_dir={'foo.bar.baz.xyz.uvw': 'src'},
      packages=['foo.bar.baz.xyz.uvw.package'],
     )

Ключевая часть здесь в том, что package_dir говорит, что "содержимое foo.bar.baz.xyz.uvw - это то, что находится в каталоге src", в то время как packages=['foo.bar.baz.xyz.uvw.package'] говорит ему ожидать, что он найдет и установит пакет с именем foo.bar.baz.xyz.uvw.package.

Эквивалент setup.cfg будет:

[options]
package_dir=
    foo.bar.baz.xyz.uvw=src
packages = foo.bar.baz.xyz.uvw.package
...