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

Python中父模块与子模块存在同名文件时如何实现正确导入?

问题根源

这个现象是Python通配导入import *的正常逻辑,和父子模块同名没有特殊关系:

  • 执行from X import *时,Python会把X模块命名空间内所有公开属性(无下划线前缀的名字,或__all__列表明确指定的名字)直接复制到当前模块的命名空间,如果存在重名,后导入的内容会直接覆盖之前绑定的同名对象。
  • 你当前的外层__init__.py先导入了外层的a、b模块,随后执行from .test import *时,test包的__init__.py已经把test内部的a、b模块注册成了test包的顶层属性,这两个同名a、b被通配导入复制到module的命名空间后,直接覆盖了之前导入的外层a、b,就出现了你看到的结果。
可行解决方案

方案1:最小改动,调整导入方式避免命名污染

直接修改外层module/__init__.py,不要用通配符导入test包的全部内容,改为显式导入test子包本身即可,不需要改其他文件:

# module/__init__.py
from . import test  # 仅绑定test子包到module命名空间,不会导入test内部的a、b
from .a import *
from .b import *

修改后效果完全符合预期:

  • module.a指向外层./module/a.py
  • module.b指向外层./module/b.py
  • module.test指向test子包,module.test.a、module.test.b正常指向test目录下的对应文件

方案2:通过__all__限制通配导入的导出范围

如果必须保留from .test import *的写法,可以在test包的__init__.py中显式定义__all__列表,指定允许被通配导入对外暴露的名字,不要把内部的a、b暴露到外层:

# module/test/__init__.py
from .a import *
from .b import *
# 仅列出需要透传到外层module的接口,a、b不要加入列表
__all__ = []  # 有其他需要暴露的函数、类可以自行添加到列表中

同时调整外层module/__init__.py的导入顺序,让外层自己的a、b最后导入,避免被覆盖:

# module/__init__.py
from .test import *
from .a import *
from .b import *

这种方式的局限性是如果test包有需要透传到外层的同名属性,依然会产生冲突,适合test包不需要向外层透传内部模块的场景。

方案3:弃用通配导入,使用精确导入(工程化推荐)

Python项目中不推荐使用import *的写法,很容易产生命名空间污染和意外覆盖,最稳妥的方式是全部使用显式精确导入:

# module/__init__.py
from . import a, b, test

# 如果需要把a、b中的特定接口暴露到module顶层,单独显式导入即可,例如:
# from .a import some_func
# from .b import SomeClass

这种写法下命名空间完全清晰,不会出现任何意外覆盖:

  • 外层a模块固定通过module.a访问
  • test子包下的a模块固定通过module.test.a访问
    是中大型Python项目普遍采用的导入规范。

内容的提问来源于stack exchange,提问作者chanjure

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:33:13