我有一个 Python 项目,其中包含多个模块、类和依赖文件(一个
requirements.txt
文件)。我想将它与所有依赖项一起打包到一个文件中,并将文件路径提供给 AWS EMR 无服务器,这将运行它。
问题是我不明白如何打包一个包含所有依赖项的 Python 项目,EMR 可以使用哪个文件等。我找到的所有示例都使用一个 Python 文件。
简单来说,如果我的Python项目不是单个文件而是比较复杂怎么办?
有几种方法可以使用 EMR Serverless 做到这一点。无论您选择哪种方式,您都需要为 EMR Serverless StartJobRun 命令提供一个主要入口点 Python 脚本。
假设您有一个这样的工作结构,其中
main.py
是创建 Spark 会话并运行您的工作的入口点,job1
和 job2
是您的本地模块。
├── jobs
│ └── job1.py
│ └── job2.py
├── main.py
├── requirements.txt
--py-files
与压缩的本地模块一起使用,--archives
与用于外部依赖项的打包虚拟环境一起使用zip -r job_files.zip jobs
venv-pack
和您的依赖项创建一个虚拟环境。注意:这必须使用与 EMR Serverless 类似的操作系统和 Python 版本来完成,因此我更喜欢使用带有自定义输出的多阶段 Dockerfile。
FROM --platform=linux/amd64 amazonlinux:2 AS base
RUN yum install -y python3
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY requirements.txt .
RUN python3 -m pip install --upgrade pip && \
python3 -m pip install venv-pack==0.2.0 && \
python3 -m pip install -r requirements.txt
RUN mkdir /output && venv-pack -o /output/pyspark_deps.tar.gz
FROM scratch AS export
COPY --from=base /output/pyspark_deps.tar.gz /
如果您运行
DOCKER_BUILDKIT=1 docker build --output . .
,您现在应该在本地系统上有一个 pyspark_deps.tar.gz
文件。
上传
main.py
、job_files.zip
和 pyspark_deps.tar.gz
到 S3 上的某个位置。
使用这样的命令运行您的 EMR 无服务器作业(替换
APPLICATION_ID
、JOB_ROLE_ARN
和 YOUR_BUCKET
):
aws emr-serverless start-job-run \
--application-id $APPLICATION_ID \
--execution-role-arn $JOB_ROLE_ARN \
--job-driver '{
"sparkSubmit": {
"entryPoint": "s3://<YOUR_BUCKET>/main.py",
"sparkSubmitParameters": "--py-files s3://<YOUR_BUCKET>/job_files.zip --conf spark.archives=s3://<YOUR_BUCKET>/pyspark_deps.tar.gz#environment --conf spark.emr-serverless.driverEnv.PYSPARK_DRIVER_PYTHON=./environment/bin/python --conf spark.emr-serverless.driverEnv.PYSPARK_PYTHON=./environment/bin/python --conf spark.executorEnv.PYSPARK_PYTHON=./environment/bin/python"
}
}'
--archives
与打包的虚拟环境这可能是最可靠的方法,但它需要您使用 setuptools。您可以使用一个简单的
pyproject.toml
文件以及现有的requirements.txt
[project]
name = "mysparkjobs"
version = "0.0.1"
dynamic = ["dependencies"]
[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}
然后您可以使用多阶段 Dockerfile 和 自定义构建输出 将您的模块和依赖项打包到虚拟环境中。
注意:这需要您启用Docker Buildkit
FROM --platform=linux/amd64 amazonlinux:2 AS base
RUN yum install -y python3
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
WORKDIR /app
COPY . .
RUN python3 -m pip install --upgrade pip && \
python3 -m pip install venv-pack==0.2.0 && \
python3 -m pip install .
RUN mkdir /output && venv-pack -o /output/pyspark_deps.tar.gz
FROM scratch AS export
COPY --from=base /output/pyspark_deps.tar.gz /
现在您可以运行
DOCKER_BUILDKIT=1 docker build --output . .
并且将生成一个包含所有依赖项的 pyspark_deps.tar.gz
文件。将此文件和您的main.py
脚本上传到S3。
假设您将两个文件都上传到
s3://<YOUR_BUCKET>/code/pyspark/myjob/
,像这样运行 EMR 无服务器作业(替换 APPLICATION_ID
、JOB_ROLE_ARN
和 YOUR_BUCKET
:
aws emr-serverless start-job-run \
--application-id <APPLICATION_ID> \
--execution-role-arn <JOB_ROLE_ARN> \
--job-driver '{
"sparkSubmit": {
"entryPoint": "s3://<YOUR_BUCKET>/code/pyspark/myjob/main.py",
"sparkSubmitParameters": "--conf spark.archives=s3://<YOUR_BUCKET>/code/pyspark/myjob/pyspark_deps.tar.gz#environment --conf spark.emr-serverless.driverEnv.PYSPARK_DRIVER_PYTHON=./environment/bin/python --conf spark.emr-serverless.driverEnv.PYSPARK_PYTHON=./environment/bin/python --conf spark.executorEnv.PYSPARK_PYTHON=./environment/bin/python"
}
}'
注意额外的
sparkSubmitParameters
指定您的依赖项并配置驱动程序和执行程序环境变量以获得 python
. 的正确路径