使用 sub-modules 打包模块的最佳实践 - 大多数使用相同的库

Best practice for packaging modules with sub-modules - most using the same libraries

我目前正在打包我自己的模块以供分发。总的来说一切正常,但是 fine-tuning/best-practice 用于构建 sub-modules 给我带来了一些麻烦。

假设模块结构为:

mdl
├── mdl
│   ├── __init__.py
│   ├── core.py
|   ├── sub_one
|   |   ├── __init__.py
|   |   └── core_sub_one.py
|   └── sub_two
|       ├── __init__.py
|       └── core_sub_two.py
├── README
└── setup.py

核心文件headers

core.pyheader开头:

import numpy as np

...some fairly large module code...

以及 core_sub_one.pycore_sub_two.pyheader 都以:

开头
import numpy as np

from .. import core as cr

所以所有子模块都需要npcr


初始化.py结构

mdl/__init__.py (core-level) 看起来像:

from . import sub_one as so
from . import sub_two as st

和两个子模块的 __init__.py 看起来像(将 one 替换为 two 另一个子模块):

from . import core_sub_one
from .core_sub_one import *

我 "learnt" 这个结构来自 numpy,见 f.i。 numpy/ma/__init__.py


问题描述

现在我在 运行 setup.py 和使用 import mdl.
导入我的模块后遇到了一些问题 submodule-access 我现在可以使用 f.i 访问我的子模块。 mdl.so.some_function_in_sub_one()。这是预期的,也是我想要的。

但是我也可以访问顶级模块cr numpy with mdl.so.crmdl.so.np, 我想避免的。 有什么办法可以避免这种情况吗? 如果不是:像这样的 importing/connecting 模块和子模块有什么缺点吗?

And 是否有关于如何在 sub-modules 中导入像 numpy 这样的库的最佳实践,当它们在 all 中需要时 个子模块?

编辑:
因为有些人似乎对要求 最佳实践 意见基础 (我知道并且我打算这样做,因为恕我直言大多数设计现实生活中的决策不是明确的二进制 1-0 决策),我必须添加:
我想遵守 scipy 中使用的模块打包样式,更具体地说 numpy,包环境。因此,如果这些软件包找到了我提出的任何问题的解决方案,这将是我最受欢迎的解决方案。

第一件事:

from .core_sub_one import *

不要这样做。是的,即使您在某些 "big name" 包中看到它,也请在某些教程或其他内容中阅读它。这是 officially considered bad practice,并且有充分的理由(根据经验,这是一个维护地狱)。

如果你真的坚持这样做(但说真的,不要这样做),至少 define an explicit __all__ var in those modules 这样你就可以控制暴露的名称(这有助于记录模块的 API).

But I can also access the top level module cr and numpy with mdl.so.cr and mdl.so.np, which I want to avoid. Is there any way to avoid this?

不是真的。如果你真的担心它,你可以在你的子模块中将这些名称作为 "protected" 导入:

# core_sub_xxx.py

import numpy as _np
from .. import core as _cr

(当然你必须替换所有出现的 'np' 和 'cr' 但任何半正经的文本编辑器都可以做到这一点)

这不会阻止对 mysubmodule._crmysubmodule._np 的访问,但至少清楚表明不应访问这些名称。

但实际上,这不是什么大问题,只要您的 API 有明确记录即可。