深度嵌套的命名空间包

Deeply nested namespaced packages

我需要维护一些以任务和管道定义为 python 包集合的方式构建的 ETL 工具。想想小内核和嵌套 namespaces/packages/subpackages 中近千个插件的插件架构。这不是一团乱麻,整体质量相当不错,但setup.py__init__.py-s看起来很hacky,有时在导入过程中会导致意想不到的问题。

我想稍微简化一下。从 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)?换句话说,是否有一种简单的方式来告诉:在foo.bar.baz.xyz.uvw命名空间中安装package

我想要这样的结构:

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

但安装过程应该将 package 放入 foo/bar/baz/xyz/uvw/package 文件夹中,以便可以使用完整路径导入。

编辑:这是个好主意吗?

这可以使用 distutils.core.setuppackage_dir 参数(或 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 说 "the contents of foo.bar.baz.xyz.uvw are what is found in the src directory",而 packages=['foo.bar.baz.xyz.uvw.package'] 告诉它期望找到并安装名为 foo.bar.baz.xyz.uvw.package.[=22 的包=]

等价于 setup.cfg 的是:

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