Python 深度嵌套的命名空间包

Python 深度嵌套的命名空间包,python,setuptools,packaging,Python,Setuptools,Packaging,我需要维护一些ETL工具,其构造方式是将任务和管道定义为python包的集合。考虑一下插件架构,它的核心很小,嵌套的名称空间/包/子包中有近千个插件。这还不是一个棘手的问题,总体质量相当好,但是setup.py和\uuuu init\uuuu.py-s看起来非常粗糙,有时在导入过程中会导致意外问题 我想简化一下。由于Python3.3,我们可以通过创建子目录而不使用\uuu init\uuuu.py将包放在名称空间中。这正是我所需要的,但我希望避免在源代码中深度嵌套子目录,因为大量的包非常小。在

我需要维护一些ETL工具,其构造方式是将任务和管道定义为python包的集合。考虑一下插件架构,它的核心很小,嵌套的名称空间/包/子包中有近千个插件。这还不是一个棘手的问题,总体质量相当好,但是
setup.py
\uuuu init\uuuu.py
-s看起来非常粗糙,有时在导入过程中会导致意外问题

我想简化一下。由于Python3.3,我们可以通过创建子目录而不使用
\uuu init\uuuu.py
将包放在名称空间中。这正是我所需要的,但我希望避免在源代码中深度嵌套子目录,因为大量的包非常小。在极端情况下,它们看起来是这样的:

$ tree
.
├── setup.cfg
├── setup.py
└── src
    └── foo
        └── bar
            └── baz
                └── xyz
                    └── uvw
                        └── package
                            ├── actual_code.py
                            └── __init__.py
$ tree
.
├── setup.cfg
├── setup.py
└── src
    └── package
        ├── actual_code.py
        └── __init__.py
有没有一种方法可以使用隐式名称空间而无需如此深入的结构,只需在
setup.py
(或者更好的
setup.cfg
)中的某个位置指定名称空间?换句话说,是否有一种简单的方法来判断:在
foo.bar.baz.xyz.uvw
名称空间中安装
package

我希望有这样的结构:

$ tree
.
├── setup.cfg
├── setup.py
└── src
    └── foo
        └── bar
            └── baz
                └── xyz
                    └── uvw
                        └── package
                            ├── actual_code.py
                            └── __init__.py
$ tree
.
├── setup.cfg
├── setup.py
└── src
    └── package
        ├── actual_code.py
        └── __init__.py
但安装过程应该将
放入
foo/bar/baz/xyz/uvw/package
文件夹,这样就可以完整路径导入


编辑:这是个好主意吗?

这可以使用
distutils.core.setup
(或
setuptools
中的等效项)的
package\u dir
参数实现

只需修改您的
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
是:

[选项]
包裹目录=
foo.bar.baz.xyz.uvw=src
packages=foo.bar.baz.xyz.uvw.packages

您是否考虑过指定
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
?这并不是让长进口变短。我需要在安装后拥有这种深层结构,但我不希望它出现在源代码存储库中。仅供参考,我找不到一种方便的方法来使用
设置工具。find_namespace_packages
(或
packages=find_namespace:
指令的
[option.packages.find]
使用
where
键)以避免需要手动列出
包的内容
,因此这确实有点多余(
foo.bar.baz.xyz.uvw
必须多次键入)。如果有人知道怎么做,请插话
find_namespace_packages
可以与列表理解一起使用,以编程方式修复前缀,但是最好使用现有的API为您完成此操作。哦,这就是它的工作方式。这几乎是完美的解决方案,谢谢!重复不是一个大问题,因为我还想为所有包创建一个模板。现在看来这是可能的(而且相当简单)。