Python自定义模块导入失败求助:ModuleNotFoundError及原因解析
嘿,我来帮你搞定这个模块导入的坑!先看你的项目结构:
F: `-- src |-- lib | `-- base.py `-- tests `-- test_modulexx `-- test_module_001.py
你遇到的报错是:
File "F:\src\tests\test_modulexx\test_module_001.py", line 2, in
from lib.base import BaseTestCase
ModuleNotFoundError: No module named 'lib'
为啥会出这个错?
Python找模块全靠sys.path这个列表里的路径,按顺序搜。你在F:\src下运行脚本,按理说F:\src应该在sys.path里,但实际可能有这些情况导致找不到:
- 路径优先级搞事情:当你直接跑
python tests/test_modulexx/test_module_001.py,Python会先把脚本所在的目录(F:\src\tests\test_modulexx)塞到sys.path最前面,虽然当前工作目录(F:\src)也在列表里,但如果测试目录里碰巧有个同名的lib.py或者lib文件夹,就会先搜到那个,导致找不到真正的lib。 - 环境变量没配置:如果你的Python环境没把
F:\src加到PYTHONPATH里,有时候(比如换了虚拟环境、IDE运行配置不对),当前工作目录可能不会自动被加入sys.path。 - 缺了包标记文件:
src、lib这些目录里没放空的__init__.py,Python不把它们当作可以导入的包,绝对导入就识别不了。
四种解决方案,按需选择
方案1:在脚本中动态添加src路径(最直接的临时解决)
在test_module_001.py的开头加一段代码,手动把src目录塞进sys.path,这样不管在哪里运行脚本都能找到lib:
import sys import os # 获取当前脚本的绝对路径,向上两级找到src目录 src_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 把src目录插入到sys.path最前面,确保优先查找 sys.path.insert(0, src_directory) # 现在可以正常导入了 import os from lib.base import BaseTestCase
优点:不用改环境,直接解决单个脚本的导入问题;缺点:每个测试脚本都要加这段代码,不够优雅。
方案2:使用相对导入(需规范项目结构)
首先在src、lib、tests目录下都创建空的__init__.py文件(让Python把这些目录当作包),然后修改导入语句为相对导入:
import os # 三个点表示向上两级目录,找到lib包 from ...lib.base import BaseTestCase
注意:相对导入的脚本不能直接双击运行,必须用模块方式执行。比如在F:\目录下运行:
python -m src.tests.test_modulexx.test_module_001
或者在F:\src目录下运行:
python -m tests.test_modulexx.test_module_001
优点:符合Python包的规范;缺点:运行方式受限,不能直接用python 脚本路径运行。
方案3:设置PYTHONPATH环境变量(全局生效)
把F:\src添加到PYTHONPATH环境变量中,这样所有Python脚本都会自动搜索这个路径:
- Windows CMD:
set PYTHONPATH=F:\src # 之后运行你的测试脚本 python tests/test_modulexx/test_module_001.py
- Windows PowerShell:
$env:PYTHONPATH = "F:\src" python tests/test_modulexx/test_module_001.py
如果想永久生效,可以在系统环境变量里添加PYTHONPATH,值设为F:\src。
优点:一次设置,所有脚本都能受益;缺点:多项目共存时可能出现路径冲突。
方案4:安装为可编辑包(最适合开发阶段)
在F:\src目录下创建pyproject.toml文件(现代Python项目推荐用这个),内容如下:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "your-project-name" version = "0.1.0" packages = ["lib"]
然后在F:\src目录下运行:
pip install -e .
之后不管在哪里运行测试脚本,都能直接from lib.base import BaseTestCase。
优点:符合Python项目最佳实践,支持虚拟环境,无路径冲突;缺点:需要配置构建文件,适合长期维护的项目。
总结
临时测试用方案1最快;正规项目开发选方案4最优;多脚本共享路径用方案3;严格遵循包结构的项目可以用方案2。
内容的提问来源于stack exchange,提问作者SparksofFire




