迁移应用目录适配Docker后运行pytest出现ModuleNotFoundError
解决FastAPI项目本地运行pytest的模块导入问题
错误根源分析
你的问题核心是Python模块搜索路径不匹配:
- Docker中正常运行是因为容器的工作目录或启动配置把项目根目录(含
app的父目录)加入了Python的sys.path,使得app作为顶层包能被正确识别。 - 当你进入
app目录直接运行pytest时,当前目录(app)没有被当作一个包,Python无法从sys.path中找到sdk对应的顶层包,导致绝对导入失败。 - 注意错误日志里的
app/sdm/sdk.py应为笔误,实际是app/sdk/sdk.py,其中的from sdk import ...是绝对导入,此时Python找不到这个顶层包。
可行解决方案
方案1:从项目根目录运行pytest(推荐)
回到包含Dockerfile和Pipfile的项目根目录,执行:
pytest app/tests/test_live_sdk.py
这样Python会自动把当前根目录加入sys.path,app作为顶层包被识别,内部的包导入逻辑(无论是绝对还是相对)都能正常工作。
方案2:修正内部包的相对导入
将sdk/sdk.py中的绝对导入改为相对导入:
# 原代码 from sdk import schemas, exceptions, constants # 修改为 from . import schemas, exceptions, constants
同时修正sdk/__init__.py的导入逻辑为相对导入:
# 原代码 import sdk # 修改为 from . import sdk
相对导入基于当前模块所在的包结构,不依赖sys.path的配置,能避免路径问题。
方案3:临时设置PYTHONPATH环境变量
如果必须在app目录下运行测试,先设置环境变量把父目录加入搜索路径:
# Linux/macOS export PYTHONPATH=$(pwd)/.. && pytest tests/test_live_sdk.py # Windows PowerShell $env:PYTHONPATH = "$(Get-Location)\.." ; pytest tests/test_live_sdk.py
方案4:在代码中动态添加路径(不推荐,仅应急)
在测试文件或sdk/__init__.py的开头添加代码,手动将父目录加入sys.path:
import sys from pathlib import Path # 获取当前文件的父目录的父目录(即项目根目录) sys.path.append(str(Path(__file__).parent.parent))
这种方式侵入性较强,不建议长期使用,优先用前面的方案。
关键导入机制说明
- 绝对导入:从
sys.path列出的目录开始查找包,比如from app import sdk需要app所在的目录在sys.path中。 - 相对导入:用
.(当前包)或..(父包)开头,仅在包内部使用,不依赖sys.path,更适合包内模块间的引用。 - 当你直接在
app目录下运行脚本时,app目录被视为普通目录而非包,所以无法通过from app import ...导入内部模块。
内容的提问来源于stack exchange,提问作者J. Santiago
相关产品推荐
相关产品推荐

