如何在SageMaker Pipeline多步骤间共享代码(无需自定义镜像)
在SageMaker Pipeline多任务间共享代码(无需自定义镜像)
问题背景
现有代码文件夹结构:
source_scripts/ ├── utils │ ├── logger.py ├── models/ │ ├── ground_truth.py │ ├── document.py ├── processing/ │ ├── processing.py │ └── main.py └── training/ ├── training.py └── main.py
尝试在training.py中用相对导入调用共享代码:
from ..common.ground_truth import GroundTruthRow
Pipeline构建代码如下:
script_processor = FrameworkProcessor() args = script_processor.get_run_args( source_dir="source_scripts", code="processing/main.py" ) step_process = ProcessingStep( code=args.code ) estimator = Estimator( source_dir="source_scripts", code="training/main.py" ) step_train = TrainingStep( estimator=estimator )
执行时触发错误:
ImportError: attempted relative import with no known parent package
需求:无需构建自定义Docker镜像,实现单个Pipeline的多个SageMaker任务间代码共享。
解决方案
1. 替换相对导入为绝对导入
SageMaker会将source_dir指定的本地目录完整复制到执行实例的工作目录,此时source_scripts下的所有子目录(utils、models等)直接处于Python的搜索路径中。
修改training.py中的导入语句为绝对路径形式:
# 导入models模块 from models.ground_truth import GroundTruthRow # 导入utils模块示例 from utils.logger import YourLoggerClass
2. 确认source_dir配置正确性
在FrameworkProcessor和Estimator中,source_dir必须指向本地的source_scripts目录。SageMaker会将该目录下的所有文件和子目录上传到任务实例,执行入口脚本(processing/main.py或training/main.py)时,工作目录即为source_scripts的根目录,确保所有子模块能被Python解释器找到。
3. 可选:添加__init__.py提升兼容性
虽然Python 3.3+支持无__init__.py的命名空间包,但为了兼容不同环境,建议在每个需要被导入的子目录下添加空的__init__.py文件,目录结构变为:
source_scripts/ ├── utils │ ├── __init__.py │ └── logger.py ├── models/ │ ├── __init__.py │ ├── ground_truth.py │ └── document.py ├── processing/ │ ├── __init__.py │ ├── processing.py │ └── main.py └── training/ ├── __init__.py ├── training.py └── main.py
4. 可选:排查导入路径问题
如果导入仍然失败,可在training.py开头添加以下代码打印Python搜索路径,确认source_scripts根目录是否在路径中:
import sys print("当前Python搜索路径:", sys.path)
查看任务执行日志即可验证路径是否正确,进而定位问题。
内容的提问来源于stack exchange,提问作者Max Markov
相关产品推荐
相关产品推荐

