1

我正在将我们公司正在开发的 python 库重组为不同的组。为避免污染顶级模块命名空间,我想将所有内容分组在顶级“companyname”包下,因此我们将拥有“conname.utils”、“conname.qa”、“conname.api”等. 其中一些预计将与我们的产品一起分发,或可公开安装。'qa' 将纯粹是内部的。

谷歌做了类似的事情。例如,protobuf 库在模块路径中以“google.protobuf”的形式提供。但是,它并不是特别干净:protobuf 包安装的 .pth 文件如下所示:

import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('google', types.ModuleType('google'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)

我认为这样做是为了欺骗导入引擎,因为“google”目录中没有 __init__.py 。但是……不优雅。

是否有一种成熟的方法来实现这一目标?我不介意让任何“coname-*”包都需要一个“coname-top”包来获取 __init__.py。我还不确定如何说服 setuptools 将包视为不在模块树的顶部,也不可能从一棵树创建子包。

为了澄清,我特别询问如何设置上述内容,以便例如可以与 coname-api 分开分发和安装 coname-qa。两者都依赖于 coname-tools 是合理的。

4

2 回答 2

1
  1. 目录 a 需要是一个包。添加一个__init__.py文件以使其成为一个包,这比一个简单的目录更上一层楼。

  2. 目录 b 也需要是 a 的子包。添加一个__init__.py文件。

  3. 目录 test 可能也应该是一个包。很难说这是否有必要。将 Python 模块的每个目录作为一个正式的包通常是一个好主意。

  4. 为了导入,包需要在 sys.path 上;这是从 PYTHONPATH 环境变量构建的。默认情况下,安装的站点包和当前工作目录是(有效地)可以找到包的仅有的两个地方。

这意味着必须安装 a,或者,您当前的工作目录也必须是 a 上一级的包。

或者,您需要将 PYTHONPATH 环境变量设置为包含 a.

于 2015-10-31T00:12:29.310 回答
1

您要做的是创建一个命名空间包。您可以使用 setuptools 来完成此操作。

请参阅https://packaging.python.org/guides/packaging-namespace-packages/#pkgutil-style-namespace-packages

设置一个结构如下的目录:

coname-utils/
    setup.py
    coname/
        utils/
            __init__.py
            ...
        ...

coname-qa/
    setup.py
    coname/
        qa/
            __init__.py
            ...
        ...

coname-api/
    setup.py
    coname/
        api/
            __init__.py
            ...
        ...

有一些变化,具体取决于您打算用于部署的工具。您可以查看上面的链接以获取详细信息。

此目录结构隔离了您希望单独安装的命名空间部分。您还可以分别对不同的子包进行版本控制,这有助于维护。大概您的某些子包之间可能存在依赖关系。您可以将代码添加到一个子包,该子包依赖于另一个子包中的 api 成员,而该子包仅存在于该子包的某些版本中。在 setup.py 文件中,您可以定义需要哪些版本的依赖项。

有关如何编写 setup.py 的详细信息,请参阅setuptools 文档

设置完成后,您应该可以使用 setuptools 构建项目,并且可以单独安装 utils、qa、api 等。一旦安装在环境中,您可以使用“import coname.utils”、“import”导入它们conname.qa”等

于 2019-04-08T18:58:53.023 回答