Python子目录导入行为不一致问题及解决方案
Python模块导入兼容问题:同时运行子模块文件与父目录入口文件
问题场景
文件结构:
a.py module/b.py module/c.py
各文件内容:
- a.py:
from module.b import hello hello()
- b.py:
from c import helloworld def hello(): helloworld() hello()
- c.py:
def helloworld(): print("Hello world")
执行结果差异:
- 进入
module目录运行python b.py,正常输出Hello world - 在父目录运行
python a.py,抛出ModuleNotFoundError: No module named 'c'
问题原因
Python的模块搜索路径(sys.path)在两种执行场景下存在差异:
- 直接运行
b.py时,Python会将**当前执行目录(即module/)**加入sys.path,因此能直接找到同目录的c.py - 通过
a.py导入module.b时,Python的sys.path是父目录,此时c.py不在搜索路径范围内,导致无法找到模块
极简解决方案
方案1:相对导入+入口判断
修改b.py,根据执行场景切换导入方式:
# 修改后的b.py if __name__ == "__main__": # 直接运行时,用当前目录的导入方式 from c import helloworld else: # 被其他模块导入时,用相对导入定位同包内的c模块 from .c import helloworld def hello(): helloworld() if __name__ == "__main__": hello()
这样既适配直接运行b.py的场景,也能满足a.py导入module.b的需求。
方案2:统一添加搜索路径
修改b.py,将自身所在目录强制加入模块搜索路径:
# 修改后的b.py import sys from pathlib import Path # 把当前文件所在的module目录加入搜索路径 sys.path.append(str(Path(__file__).parent)) from c import helloworld def hello(): helloworld() if __name__ == "__main__": hello()
这种方式无需区分执行场景,不管是直接运行还是被导入,Python都能找到c模块。
额外说明
可以给module目录添加空的__init__.py文件,将其标记为正式Python包,但上述方案不依赖该文件也能正常生效。
内容的提问来源于stack exchange,提问作者Rolf
相关产品推荐
相关产品推荐

