Python包顶层导入模块内容的正确方式及导入现象疑问
问题
我有一个采用如下标准结构的Python包:
pkg ├── LICENSE ├── pyproject.toml ├── README.md ├── src │ └── pkg │ ├── __init__.py │ ├── mod.py │ └── subpkg │ ├── __init__.py │ └── submod.py └── tests
其中模块pkg/src/pkg/mod.py包含函数foo(),我希望能在包顶层加载该模块,从而可以通过如下语法调用foo():
>>> pkg.foo()
我目前的做法是在pkg/src/pkg/__init__.py中写入如下代码:
from .mod import * from . import subpkg
但调用dir(pkg)时,发现mod.py对应的模块也被列出:
>>> dir(pkg) ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'foo', 'mod', 'subpkg']
这种情况是否正常?正确的实现方式是什么?希望能得到相关建议。
解决方案与解释
1. 实现pkg.foo()的正确写法
如果你只想把foo暴露在包顶层,避免引入mod模块对象,不要使用from .mod import *,而是显式导入指定函数:
# pkg/src/pkg/__init__.py from .mod import foo from . import subpkg
这样执行dir(pkg)时,只会显示foo和subpkg,不会出现mod模块对象。
2. import *导致mod出现的原因
当你执行from .mod import *时,Python会将mod模块中所有非下划线开头的成员导入到当前包的命名空间,但同时,Python的导入机制会自动把mod模块本身也添加到当前包的命名空间中(用于追踪导入来源),所以dir(pkg)会显示mod,这是Python的默认行为。
3. 这种情况是否正常?
用import *导致mod出现在dir(pkg)里是正常的,但这并非最佳实践:
- 显式导入指定成员更清晰,能避免潜在的命名冲突;
- 减少不必要的模块对象暴露,让包的顶层API更简洁,符合Python的“显式优于隐式”原则。
4. 额外建议
- 如果
mod中有多个需要暴露的函数或类,逐个显式导入即可:from .mod import foo, bar, BazClass - 若确实需要批量导入但不想暴露
mod模块对象,可以先导入模块再赋值后删除模块引用:
不过这种写法不如显式导入直观,仅在特殊场景下使用。from . import mod foo = mod.foo bar = mod.bar del mod # 删除模块对象,避免其出现在包的命名空间中
内容的提问来源于stack exchange,提问作者argentum_109
相关产品推荐
相关产品推荐

