从子文件夹导入Python模块遇ModuleNotFoundError问题求助
ModuleNotFoundError: No module named 'app'及相对导入报错的问题 我来帮你梳理下这个问题的根源和解决办法,毕竟在AWS Lambda环境下搞Python包导入确实容易踩坑!
问题到底出在哪?
你遇到的两个报错本质都是Python找不到模块的搜索路径:
- 用绝对导入
import app.parsers.company_1时,不管是本地还是Lambda环境,Python的sys.path里都没包含能定位到app模块的路径; - 之前尝试相对导入时的
attempted relative import with no known parent package,是因为你直接运行了company_1.py脚本——此时它被当成了一个独立的顶级脚本,而不是app包的一部分,所以相对导入规则不生效。
结合你的场景(要把src内容上传Lambda,且需要固定顶级文件夹做绝对导入),我们分本地开发和Lambda部署两种情况来解决:
本地开发时的修复方法
方法1:手动把src目录加入Python搜索路径
在company_1.py最开头加一段代码,让Python能找到app模块的父目录:
import sys from pathlib import Path # 找到当前脚本所在的src目录(往上跳三级:writers → app → src) src_folder = Path(__file__).parent.parent.parent sys.path.append(str(src_folder)) # 现在就能正常导入了 import app.parsers.company_1 as parser_1
方法2:用模块模式运行脚本
别直接双击或者python company_1.py运行,先切换到包含src的那个上级目录,然后用-m参数以模块方式执行:
python -m src.app.writers.company_1
这种方式会自动把当前目录加入sys.path,Python就能识别到src下的app模块了。
Lambda部署时的正确姿势
Lambda的执行环境默认把/var/task(也就是你上传的zip包解压后的目录)加入sys.path,所以只要包结构和handler配置对了,绝对导入就能正常工作:
1. 确保部署包结构正确
你打包上传的zip文件,解压后在/var/task下的结构应该是这样的:
├── __init__.py # 原来src目录下的那个__init__.py └── app ├── __init__.py ├── getters/ ├── parsers/ └── writers/
简单说就是:app文件夹直接在zip包的根目录,和src下的__init__.py同级,不能把整个src文件夹打包进去!
2. 配置正确的Lambda Handler
如果你的write_data函数在app.writers.company_1里,那么Lambda的Handler要填:
app.writers.company_1.write_data
这样Lambda会从/var/task(已经在sys.path里)找到app模块,再定位到你的函数。
更规范的替代方案:用相对导入
其实相对导入更符合Python包的设计规范,之前报错是因为你直接运行了脚本。改成相对导入后,只要是作为包的一部分被加载(比如Lambda环境中),就能正常工作:
把company_1.py里的导入改成:
from ..parsers import company_1 as parser_1
..表示往上跳一级目录(从writers到app),这样就能找到同级的parsers模块了。
总结一下
- 本地开发:要么手动加路径,要么用
-m参数运行; - Lambda部署:保证包结构正确,handler配置到位;
- 相对导入是更优的写法,但要避免直接运行脚本。
内容的提问来源于stack exchange,提问作者Nanna




