使用--py-files提交PySpark任务时无法找到模块路径的问题排查
问题场景
在EMR集群提交PySpark任务时,指定S3中的pipeline.zip作为依赖包,提交命令如下:
/bin/spark-submit \ --py-files s3://my-dev/scripts/job-launchers/dev/pipeline.zip \ pipeline.job_1.job_1.py -h
pipeline.zip的结构为:
$ unzip -L pipeline.zip Archive: pipeline.zip extracting: pipeline/__init__.py creating: pipeline/common/ inflating: pipeline/common/__init__.py inflating: pipeline/common/error_message.py creating: pipeline/job_1/ inflating: pipeline/job_1/__init__.py inflating: pipeline/job_1/job_1.py creating: pipeline/job_2/ inflating: pipeline/job_2/__init__.py inflating: pipeline/job_2/job_2.py
该包存储在 s3://my-dev/scripts/job-launchers/dev/,已确认文件存在:
$ aws s3 ls s3://my-dev/scripts/job-launchers/dev/pipeline.zip 2024-10-11 17:54:28 13219 pipeline.zip
提交后报错:
/usr/bin/python3: can't open file '/home/hadoop/pipeline.job_1.job_1.py': [Errno 2] No such file or directory
以下是具体排查思路:
排查思路
修正主脚本的指定方式
spark-submit将.分隔的路径当作本地文件查找才会报错,正确的做法是用-m参数指定Python模块运行,同时去掉.py后缀。修改后的命令:/bin/spark-submit \ --py-files s3://my-dev/scripts/job-launchers/dev/pipeline.zip \ -m pipeline.job_1.job_1 -h这样Spark会从
--py-files加载的包中识别并运行目标模块。验证压缩包结构合法性
确保pipeline.zip的根目录直接是pipeline文件夹,无多余上层目录。重新打包时,需在pipeline目录的上级执行压缩命令:zip -r pipeline.zip pipeline/解压后直接得到
pipeline目录,才能被Python正确识别为可导入的包。检查EMR集群对S3的访问权限
确认EMR集群的服务角色(如EMR_EC2_DefaultRole或自定义角色)拥有该S3路径的s3:GetObject和s3:ListBucket权限。可在集群节点上执行以下命令测试:aws s3 cp s3://my-dev/scripts/job-launchers/dev/pipeline.zip /tmp/test.zip unzip /tmp/test.zip -d /tmp/test ls /tmp/test/pipeline/job_1/若能成功下载解压,说明权限正常;否则需调整IAM角色的权限策略。
显式配置PYTHONPATH
提交任务时显式设置PYTHONPATH,确保驱动和执行器都能识别依赖包路径:PYTHONPATH=/tmp/spark-scripts:$PYTHONPATH /bin/spark-submit \ --py-files s3://my-dev/scripts/job-launchers/dev/pipeline.zip \ -m pipeline.job_1.job_1 -h或通过Spark配置参数指定:
/bin/spark-submit \ --conf spark.driverEnv.PYTHONPATH=/tmp/spark-scripts \ --conf spark.executorEnv.PYTHONPATH=/tmp/spark-scripts \ --py-files s3://my-dev/scripts/job-launchers/dev/pipeline.zip \ -m pipeline.job_1.job_1 -h本地模式验证包结构
在EMR主节点下载并解压pipeline.zip,直接运行Python模块验证:unzip pipeline.zip -d /tmp PYTHONPATH=/tmp python3 -m pipeline.job_1.job_1 -h若本地运行正常,说明问题出在Spark提交参数配置;若本地也报错,需检查包结构或代码本身。
内容的提问来源于stack exchange,提问作者Smruti Prakash Mohanty

