使用AWS Lambda(Python 3)读取存储在S3中的Parquet文件

11

我正在尝试使用AWS Lambda加载、处理和写入S3中的Parquet文件。我的测试/部署过程如下:

似乎有两种可能的方法,它们在docker容器中本地都有效:

  1. 使用s3fs的fastparquet: 不幸的是,打包后的包的大小大于256MB,因此我无法使用它更新Lambda代码。
  2. 使用s3fs的pyarrow:我遵循了https://github.com/apache/arrow/pull/916,当用Lambda函数执行时,我会得到以下结果:

    • 如果我在URI前缀中加上S3或S3N(如代码示例中):在Lambda环境中,会出现pyarrow/parquet.py中的OSError: Passed non-file path: s3://mybucket/path/to/myfile错误。本地运行时,在pyarrow/parquet.py的第714行会出现IndexError: list index out of range
  3. 如果我不在URI前加S3或S3N:它在本地工作(我可以读取parquet数据),但在Lambda环境中,我会在pyarrow/parquet.py的848行收到相同的OSError: Passed non-file path: s3://mybucket/path/to/myfile
  4. 我的问题是:

    • 为什么Docker容器中的结果与Lambda环境中的结果不同?
    • 给URI的正确方式是什么?
    • 是否有一种接受的方法可以通过AWS Lambda读取S3中的Parquet文件?

    谢谢!

4个回答

8
AWS有一个项目( AWS数据整理器),可以完全支持Lambda层。
文档中有一个逐步操作的步骤。
代码示例:
import awswrangler as wr

# Write
wr.s3.to_parquet(
    dataframe=df,
    path="s3://...",
    dataset=True,
    database="my_database",  # Optional, only with you want it available on Athena/Glue Catalog
    table="my_table",
    partition_cols=["PARTITION_COL_NAME"])

# READ
df = wr.s3.read_parquet(path="s3://...")

参考资料


3
我成功地使用fastparquet将parquet文件写入S3。这有点棘手,但我的突破是当我意识到要组合所有依赖项时,我必须使用与Lambda使用的完全相同的Linux。

以下是我的做法:

1. 使用与Lambda使用的Amazon Linux镜像启动EC2实例

Source: https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

Linux镜像: https://console.aws.amazon.com/ec2/v2/home#Images:visibility=public-images;search=amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2

注意:由于这个Linux系统不是用于开发的,你可能需要安装许多软件包并将Python版本更改为3.6。以下是我查找软件包的方法:

sudo yum list | grep python3

我安装了:

python36.x86_64
python36-devel.x86_64
python36-libs.x86_64
python36-pip.noarch
python36-setuptools.noarch
python36-tools.x86_64

2. 使用此处的指令构建了一个包含我脚本所需依赖项的zip文件,将它们全部倾倒到一个文件夹中,然后使用以下命令将它们压缩:

mkdir parquet
cd parquet
pip install -t . fastparquet 
pip install -t . (any other dependencies)
copy my python file in this folder
zip and upload into Lambda

注意:我必须解决一些限制问题:Lambda不允许上传大于50M的zip文件和未压缩大小超过260M的文件。如果有人知道更好的将依赖项导入Lambda的方法,请分享。
来源: 从AWS Kinesis firehose将parquet写入AWS S3

针对 pyarrow 的多 Linux 变量,如果只保留所有 *16 文件,并且删除每个 lib 的其他较大副本,然后将它们重新打包成一个 zip 文件,那么 lambda 包的大小将小于 250 ,这是 AWS Lambda 可接受的。 - nitinr708

2

这是一个环境问题(Lambda在VPC中无法访问存储桶)。现在Pyarrow可以正常工作。
希望这个问题本身能够提供足够好的概述,告诉如何使所有内容正常工作。


你能提供更多关于如何让它工作的信息吗?即使pyarrow包在我的zip文件中,我仍然遇到了ImportError。它一直说“需要pyarrow支持parquet”。我正在运行Python 2.7,这可能是问题所在。 - vertigokidd
可能是这样,但没有上下文很难诊断。不过,您的错误看起来不像是ModuleNotFoundError或ImportError。我按照我给出的链接创建了我的环境。大致步骤: docker run -it lambci/lambda:build-python3.6 bashmkdir lambdacd lambda virtualenv ~/lambda source ~/lambda/bin/activate pip install pyarrow pip install pandas pip install s3fs cd $VIRTUAL_ENV/lib/python3.6/site-packages zip -r9 ~/lambda.zip . [在本地获取lambda.zip] zip -ur ../lambda.zip lambda_function.py - Ptah
感谢@Ptah的回复。我猜测这可能是AWS Lambda中Python 2.7运行时不兼容的问题,结果证实了我的猜测。一旦我将代码升级到3.6并构建了升级后的zip文件,pyarrow就可以正常工作了。希望这能帮助其他遇到类似问题的人。 - vertigokidd
你能给我们提供一段代码示例吗?我想知道你是如何编写文件并使用s3fs对象的...我正在尝试使用pyarrow.parquet.write_table(),但对我来说不起作用。谢谢! - phoenix

0

通过 AWS sam cli 和 Docker 也可以实现此目标(我们稍后会解释这个需求)。

1.创建一个目录并初始化 sam

mkdir some_module_layer
cd some_module_layer
sam init

通过输入最后一个命令,会提示一系列三个问题。可以选择以下答案序列(我正在考虑在Python3.7下工作,但其他选项也可能可行)。

1 - AWS快速启动模板

8 - Python 3.7

项目名称[sam-app]:some_module_layer

1 - Hello World示例

2. 修改requirements.txt文件

cd some_module_layer
vim hello_world/requirements.txt

这将在vim上打开requirements.txt文件,在Windows上,您可以输入code hello_world/requirements.txt来在Visual Studio Code上编辑该文件。

3. 将pyarrow添加到requirements.txt中

除了pyarrow之外,还应包括pandass3fs。 在这种情况下,包括pandas将避免其不将pyarrow识别为读取parquet文件的引擎。

pandas
pyarrow
s3fs

4. 使用容器构建

在运行sam build命令时,需要使用Docker并添加选项--use-container。如果是第一次使用,它将拉取lambci/lambda:build-python3.7 Docker镜像。

sam build --use-container
rm .aws-sam/build/HelloWorldFunction/app.py
rm .aws-sam/build/HelloWorldFunction/__init__.py
rm .aws-sam/build/HelloWorldFunction/requirements.txt

请注意,我们只保留Python库。
5. 压缩文件。
cp -r .aws-sam/build/HelloWorldFunction/ python/
zip -r some_module_layer.zip python/

在Windows上,运行Compress-Archive python/ some_module_layer.zip可以起作用。
6. 将zip文件上传到AWS
以下link对此非常有用。

你能在Mac OS上运行这些命令吗?还是这种方法需要在Linux机器上运行? - Powers
@Powers,它们可以在Mac、Linux和Windows上运行。你是否遇到了任何错误? - Miguel Trejo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接