Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 直接从setuptools中的命名空间包导入_Python_Setuptools_Namespace Package - Fatal编程技术网

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
函数,因此您可能不应该劫持此名称。