You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:03:32