You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

从子文件夹导入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

..表示往上跳一级目录(从writersapp),这样就能找到同级的parsers模块了。


总结一下

  • 本地开发:要么手动加路径,要么用-m参数运行;
  • Lambda部署:保证包结构正确,handler配置到位;
  • 相对导入是更优的写法,但要避免直接运行脚本。

内容的提问来源于stack exchange,提问作者Nanna

火山引擎 最新活动