如何将模块用作namespace package和特定子项目中的类的容器?也就是说,如何直接从命名空间包而不是其子包导入某些内容?
一个例子可以使问题更清楚。
calc
假设我想创建一个名为calc
的命名空间包,其上有三个项目(sscce:calcs.tar.gz)。第一个在calc-add
目录中找到,具有以下结构:
calc-add/calc/
calc-add/calc/add.py
calc-add/calc/__init__.py
calc-add/calc/__init__.py
的内容只是
__import__('pkg_resources').declare_namespace(__name__)
根据命名空间包的要求,add.py
只有以下函数:
def op(n1, n2):
return n1 + n2
在calc-sub
目录中还有另一个项目具有以下结构:
calc-sub/calc/
calc-sub/calc/sub.py
calc-sub/calc/__init__.py
__init__.py
文件与上一个文件相同,sub.py
只有一个简单的函数:
def op(n1, n2):
return n1 - n2
最后,我有一个calc-main
目录,其中包含以下内容:
calc-main/calc/
calc-main/calc/main.py
calc-main/calc/__init__.py
同样,__init__.py
只有提到的行,但main.py
有以下代码:
import calc.add, calc.sub
def apply(n1, n2, op):
if op == "add":
return calc.add.op(n1, n2)
else:
return calc.sub.op(n1, n2)
apply()
函数如果我调用带有$PYTHONPATH
设置如下的Python解释器:
$ PYTHONPATH=$PYTHONPATH:../calc-add/:../calc-sub/ python
然后我可以这样打电话给apply()
:
>>> import calc.main
>>> calc.main.apply(2, 3, 'add')
5
但是,我想直接从apply()
致电calc
,如下所示:
>>> import calc
>>> calc.apply(2, 3, 'add')
5
如果我将以下行添加到calc-main/calc/__init__.py
:
from main import apply
然而,setuptools文档非常明确:
您不得在名称空间包的__init__.py中包含任何其他代码和数据。即使它在开发期间似乎有效,或者当项目作为.egg文件安装时,当使用" system"安装项目时它也不起作用。打包工具 - 在这种情况下,不会安装__init__.py文件,更不用说执行了。
那么如何在不打破__init__.py
文件限制的情况下获得我想要的内容呢?这可能吗?