如何解决从项目子目录运行Python文件时的模块导入错误?
遇到这种问题其实是Python模块搜索路径的规则在“搞鬼”,我来给你拆解清楚原因,再给你几个实用的解决办法:
问题到底出在哪?
当你直接执行./kalman/find_observibility.py时,Python会把这个脚本所在的kalman/目录加到模块搜索路径sys.path的最前面,而不是你的项目根目录。这时候代码里的from kalman import ...语句,会被Python误判为要在kalman/目录下找kalman相关模块,而不是把上层的整个kalman文件夹识别为一个标准Python包,自然就会弹出模块找不到的错误。
而你把脚本复制到项目根目录后能正常运行,是因为此时Python会自动把项目根目录加入sys.path,kalman作为根目录下的合法包被正确识别,所有内部导入逻辑都能正常解析。
实用解决办法
方法一:用模块方式从根目录运行(最推荐)
切换到你的项目根目录,执行以下命令:
python3 -m kalman.find_observibility
这种方式是Python官方推荐的包内脚本运行方式,它会自动把项目根目录加入模块搜索路径,让kalman被完整识别为一个包,所有内部的导入语句都能按预期工作,完全不需要修改任何代码。
方法二:手动给脚本添加项目根目录到搜索路径
如果你确实需要直接运行子目录里的脚本,可以在find_observibility.py的最开头(所有导入语句之前)添加一段代码,手动把项目根目录加入Python的模块搜索路径:
#! /usr/bin/env python3 import sys from pathlib import Path # 获取项目根目录:当前脚本所在目录的父目录 project_root = Path(__file__).parent.parent sys.path.append(str(project_root)) # 以下是原来的导入和业务代码 from kalman import outputJacobian, stateJacobian, stateTransition from make_flight import Rising, Rounds if '__main__' == __name__: print('oh my')
这样不管你从哪个位置运行这个脚本,它都会自动定位到项目根目录并加入搜索路径,确保from kalman import ...能找到正确的包。
方法三:改用相对导入(适合包被导入的场景)
如果你的kalman包主要是用来被其他代码导入使用,而不是经常直接运行子目录里的脚本,可以把包内部的导入语句改成相对导入:
比如把kalman/kalman.py里的:
from kalman.model import modelOutput, stateTransition
修改为:
from .model import modelOutput, stateTransition
不过要注意:相对导入在直接运行脚本时会报错,所以这种方式更适合kalman作为包被外部代码导入的场景,而非直接运行子目录脚本的情况。
备注:内容来源于stack exchange,提问作者Tim Wescott

