3

如何将模块用作命名空间包和特定子项目中类的容器?也就是说,我怎样才能直接从命名空间包而不是它的子包中导入一些东西?

一个例子可以使问题更清楚。

三个分包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()函数

如果我使用如下设置调用 Python 解释器$PYTHONPATH

$ 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 文件时,当使用“系统”打包工具安装项目时它不会工作——在这种情况下,不会安装 __init__.py 文件,更不用说执行了。

那么如何在不打破文件限制的情况下获得我想要的东西__init__.py呢?那可能吗?

4

0 回答 0