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