如今,在serverless环境中使用Polars与在本地使用Polars非常相似。因为Polars现在内置了对在eager模式和lazy模式下从云存储(如AWS S3)读取和写入的支持,我们通常可以在处理程序函数中编写标准的Polars语法。
在这个例子中,我将向你展示如何在Docker镜像中创建一个AWS Lambda函数。在Docker中进行这种操作的一个好处是,你可以在将Lambda函数部署到AWS之前,在本地对它们进行测试。
我们首先在一个requirements.txt文件中定义我们的依赖项。我们所需要的只是Polars和用于在eager模式下与云存储中的文件一起工作的库。
polars fsspec s3fs
在实际的生产查询中,我强烈建议你锁定你的依赖项的版本。根据我的经验,与云存储一起工作的库会频繁更新,而pip在协调不同版本时经常会遇到问题。
接下来,我们使用最新的Python运行时在Dockerfile中定义我们的Docker镜像。我们使用一个为基础Docker镜像,该镜像专为运行lambda函数而创建。
这个镜像的一个特点是它有一个名为LAMBDA_TASK_ROOT的变量,该变量指向运行lambda函数的目录。这对于将文件复制到镜像中很有用。
# Use a python image from AWSFROM public.ecr.aws/lambda/python:3.11 # Copy requirements.txt into the right directory for the lambda functionCOPY requirements.txt ${LAMBDA_TASK_ROOT} # Install the specified packages (and cache the downloaded packages)RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt # Copy function codeCOPY lambda_function.py ${LAMBDA_TASK_ROOT} # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)CMD [ "lambda_function.handler" ]
在Dockerfile的pip install行之前,我添加了一个命令来缓存下载的Python包。这在开发函数时可以节省大量时间。我将在下面详细解释这一点。
现在我们需要编写一个Python脚本,该脚本在lambda函数被调用时运行。在这个函数中,我们将以急切模式从S3读取一个Parquet文件,按列进行分组,并计算另一列的平均值。我将结果以JSON格式获取。
import polars as pl def handler(event, context): try: # Define the object url url = "s3://<bucket_name>/test_file.pq" # Download and read the parquet file df = ( pl.read_parquet( url, columns=["id1", "v1"], ) .groupby("id1") .agg(pl.col("v1").mean()) ) # Return the dataframe as json return df.write_json() except Exception as err: # Return the error if something goes wrong return err
在使用Docker时,我经常编写一个shell脚本来构建镜像、在本地运行容器并将其部署到云端。
在这个示例的shell脚本中,当运行容器时,我将我的.aws文件夹挂载到容器中的.aws文件夹。这种挂载允许我在本地运行时使用我的AWS凭据来访问S3存储桶。
#!/bin/bash# Build the docker image docker build --platform linux/amd64 -t docker-image:test .# Run the docker image locally# Open port 9000 on the host and map it to port 8080 in the container# Mount the .aws folder in the home directory to the .aws folder in the container docker run --platform linux/amd64 -p 9000:8080 -v ~/.aws:/root/.aws docker-image:test
我们现在可以通过向端口9000上的本地端点发送请求来在本地测试lambda函数。
curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
如果在本地运行,会看到简单函数的输出以JSON格式显示。
下一步
从这一点开始,你需要在AWS中创建一个Elastic Container Repository(ECR),并将你的镜像推送到其中。然后,你可以创建一个lambda函数,该函数使用你的镜像作为容器。关于这些步骤的更多详细信息,请参阅AWS的教程。
关于优化Polars和AWS Lambda,还有很多要说的。例如,你可以使用Polars以懒加载模式从S3读取和写入数据,这使得Polars能够应用查询优化。我将在未来的帖子中讨论这一点。
我们还可以考虑如何根据我们在S3中存储数据的方式来加快查询速度。例如,我们可以使用分区的Parquet文件来使查询更加高效。我在我的研讨会上提到了这一点,并且我也会在未来的博客文章中讨论它。
往期热门文章:
从 Pandas 到 Polars 二十六:在Polars中,不要遍历列
从 Pandas 到 Polars 二十三:如果你的数据已经排序,Polars可以为你提供助力
从 Pandas 到 Polars 十八:数据科学 2025,对未来几年内数据科学领域发展的预测或展望
从 Pandas 到 Polars 十三:流式处理的关键参数
从 Pandas 到 Polars 十:“Polars 表达式“是什么?