python - 使用 __all__ 传播模块导入到顶部
问题描述
我想将一些模块(utils)传播到顶部,但也控制使用传播的内容__all__
例如:
有一个包all
,其中的内容__init__
被导入alpha_utils
,所以从用户的角度来看,这些方法就像来自alpha_utils
.
包也alpha_utils
由模块导入top_utils_module
。
我想要做:
top_utils_module.beta_fn
(即使beta_fn
在all
包装中)
top_utils_module.alpha_fn
(即使beta
在alpha_utils
包装中)
我可以使用 alwaysimport from <some_module_name> all
但我想通过使用来控制每个模块公开的内容__all__
。
使用下面的结构是行不通的,我可以得到我想要的东西,但不能降低两层。
-- top_2 utils_module
...
+-- alpha_utils
| -- __init__
| -- alpha_module_1
| -- alpha_module_2
| -- alpha_module_3
....
+-- all
| -- __init__
| -- all_module_1
| -- all_module_2
| -- all_module_3
在all
文件夹中__init__
:
from .all_module_1 import fun1, fun12
from .all_module_2 import fun2
from .all_module_3 import fun3
__all__ = ["fun1", "fun2", "fun12", "fun2", "fun3"]
在alpha_utils
文件夹中__init__
:
from ..all import *
_all__ = ["alpha_module_1", "alpha_module_2", "alpha_module_3"] ## ? how to integrate ..all
在top_2 utils_module
:
from some.tir import tir
from alpha_utils import *
解决方案
问题
回顾和简化,因为这个问题有点吵,很难理解。有3个模块/包。
术语表:import package、module和to export
__all__
我的意思是通过在模块级属性中定义一系列符号名称来传达模块/包的公共 API 的范围。
a
-- 我们希望最终用户从中使用 API 的顶级模块;它从b
b
-- 导出自己的模块的导入包,但也重新导出导入包中的符号c
c
-- 从其模块中导出单个符号的导入包
b
根模块应该是__init__.py
什么样子?
一个解法
从一个角度来看,这是一种解决方法,解决方案是更改需求并a
直接从c
. 但从另一个角度来看,根据您对代码所有权和团队责任的引用,它可能正是您想要的。
我的示例导入包如下所示。
├── a.py
├── b
│ ├── bm1.py
│ ├── bm2.py
│ └── __init__.py
└── c
├── _cm1.py
├── _cm2.py
└── __init__.py
c/__init__.py
因为
c
我假设它的模块是内部的,因为它从中导出特定的功能,因此它们以下划线开头。from ._cm1 import cm1_fn1, cm1_fn2 from ._cm2 import cm2_fn1, cm2_fn2 __all__ = 'cm1_fn1', 'cm1_fn2', 'cm2_fn1', 'cm2_fn2'
c/_cm1.py
def cm1_fn1(): pass def cm1_fn2(): pass
c/_cm2.py
def cm2_fn1(): pass def cm2_fn2(): pass
b/__init__.py
因为
b
我假设它的模块是公共的并且有自己的公共 API。请注意,修改
globals
的 将来会有一些名称冲突的风险。此外,一些代码分析工具可能无法理解修改。from . import bm1, bm2 from .. import c __all__ = ('bm1', 'bm2') + c.__all__ _own_scope = globals() for name in c.__all__: _own_scope[name] = getattr(c, name)
b/bm1.py
__all__ = 'bm1_fn1', def bm1_fn1(): pass
b/bm2.py
__all__ = 'bm2_fn1', def bm2_fn1(): pass
a.py
from .b import * from .b import __all__
有了这个,我可以跳出目录,说 namedso66939804
并运行以下python3
REPL。
>>> from so66939804 import a
>>> a.__all__
('bm1', 'bm2', 'cm1_fn1', 'cm1_fn2', 'cm2_fn1', 'cm2_fn2')
>>> dir(a)
['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'bm1', 'bm2', 'cm1_fn1', 'cm1_fn2', 'cm2_fn1', 'cm2_fn2']
推荐阅读
- linux - 如何为这个命令管道 docker-compose logs -f 设置别名?
- python - 无法在 Catalina 上正确安装 Python 3 / Jupyter
- angular - Angular 中惯用的条件 TypeScript 编译
- python - 将项目列表应用于views.py中的每个视图
- python - Python内部方法无法从外部方法获取变量
- javascript - 使用 useState 响应不重新渲染状态更改
- python - Matplotlib 图像显示在 Heroku 中托管的 Flask 应用程序上
- flutter - Flutter:如何制作屏幕的可滚动菜单?
- github - 我可以像在 github 或 gitlab 上那样在 Sonatype nexus3 存储库中存储和访问文件吗?
- c# - 如何在字符串变量中运行 ASM 操作码或将其转换为字节?