Python 直接从setuptools中的命名空间包导入
如何将模块用作特定子项目中类的容器和容器?也就是说,如何直接从命名空间包而不是其子包导入内容 举个例子可以使问题更清楚 三个子包Python 直接从setuptools中的命名空间包导入,python,setuptools,namespace-package,Python,Setuptools,Namespace Package,如何将模块用作特定子项目中类的容器和容器?也就是说,如何直接从命名空间包而不是其子包导入内容 举个例子可以使问题更清楚 三个子包calc 假设我想创建一个名为calc的命名空间包,其中有三个项目(:)。第一个位于calc add目录中,具有以下结构: calc-add/calc/ calc-add/calc/add.py calc-add/calc/__init__.py calc-sub/calc/ calc-sub/calc/sub.py calc-sub/calc/__init__.py
calc
假设我想创建一个名为calc
的命名空间包,其中有三个项目(:)。第一个位于calc add
目录中,具有以下结构:
calc-add/calc/
calc-add/calc/add.py
calc-add/calc/__init__.py
calc-sub/calc/
calc-sub/calc/sub.py
calc-sub/calc/__init__.py
calc add/calc/_init__.py
的内容只是
__import__('pkg_resources').declare_namespace(__name__)
根据命名空间包的要求,和add.py
仅具有以下功能:
def op(n1, n2):
return n1 + n2
def op(n1, n2):
return n1 - n2
另一个项目位于calc sub
目录下,具有以下结构:
calc-add/calc/
calc-add/calc/add.py
calc-add/calc/__init__.py
calc-sub/calc/
calc-sub/calc/sub.py
calc-sub/calc/__init__.py
\uuuu init\uuuu.py
文件与上一个文件相同,并且sub.py
只有一个简单的功能:
def op(n1, n2):
return n1 + n2
def op(n1, n2):
return n1 - n2
最后,我有一个包含以下内容的calc main
目录:
calc-main/calc/
calc-main/calc/main.py
calc-main/calc/__init__.py
同样,\uuuuu init\uuuuuuuuuuupy
只有提到的行,但是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()
函数
如果调用Python解释器时,$PYTHONPATH
设置如下:
$ PYTHONPATH=$PYTHONPATH:../calc-add/:../calc-sub/ python
>>> import calc
>>> calc.apply(2, 3, 'add')
5
然后我可以这样调用apply()
:
>>> import calc.main
>>> calc.main.apply(2, 3, 'add')
5
但是,我想直接从calc
调用apply()
,如下所示:
$ PYTHONPATH=$PYTHONPATH:../calc-add/:../calc-sub/ python
>>> import calc
>>> calc.apply(2, 3, 'add')
5
如果我将以下行添加到calc main/calc/\uuu init\uuuu.py
,它显然可以工作:
from main import apply
但是,setuptools文档非常清楚:
在名称空间包的_uinit__uuuu.py中不能包含任何其他代码和数据。即使在开发过程中,或者当项目作为.egg文件安装时,它似乎可以工作,但当使用“系统”打包工具安装项目时,它将不工作——在这种情况下,将不会安装_uinit _;.py文件,更不用说执行了
那么,我如何才能在不打破
\uuuu init\uuuuuuuy.py
文件限制的情况下得到我想要的呢?这可能吗?我认为你不能很容易地解决这个问题。。。我的解决方案是将所有内容移动到一级命名空间“core”包,在您的情况下,它将是calc.core
。您还可以在命名空间包名称中使用点,例如calc.add
而不是calc add
。大多数名称空间的Python包都是这样做的。@Mikkoohtama不用担心,在我的示例中,包确实是点分隔的。连字符的目录只是我假设项目的根目录。此外,我使用的几乎正是您目前提出的解决方案—只需调用模块main
,而不是core
。然而,我将继续寻找并等待答案。这种限制来自这样一个事实,即任何名称空间包都可以是sys.path上的第一个名称空间包。然后它调用pkg_resources.declare_namespace和/或pkgutil.extend_path,扫描sys.path的其余部分,以查找名称空间包的更多副本,并将它们添加到包的路径中。如果您在init.py中提供了任何其他代码,那么您必须在每个init.py中复制相同的代码,因为任何副本都可以“赢得”首先导入的竞争,具体取决于sys.path。而且Python具有内置的apply
函数,因此您可能不应该劫持此名称。