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

Posted

技术标签:

【中文标题】使用 AWS Lambda (Python 3) 读取存储在 S3 中的 Parquet 文件【英文标题】:Read Parquet file stored in S3 with AWS Lambda (Python 3) 【发布时间】:2018-06-07 15:14:10 【问题描述】:

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

https://github.com/lambci/docker-lambda 作为模拟 Amazon 环境的容器,因为需要安装本机库(其中包括 numpy)。 这个程序生成一个zip文件:http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example-deployment-pkg.html#with-s3-example-deployment-pkg-python 在 zip 中添加一个测试 python 函数,将其发送到 S3,更新 lambda 并对其进行测试

似乎有两种可能的方法,都可以在 docker 容器本地工作

    fastparquet with s3fs:不幸的是,解压后的包大于 256MB,因此我无法用它更新 Lambda 代码。

    带有 s3fs 的 pyarrow:我关注了https://github.com/apache/arrow/pull/916,当使用 lambda 函数执行时,我得到:

    如果我在 URI 前加上 S3 或 S3N(如代码示例中所示):在 Lambda 环境中 OSError: Passed non-file path: s3://mybucket/path/to/myfile 在 pyarrow/parquet.py 中,第 848 行。本地我在 pyarrow/ 中得到 IndexError: list index out of range parquet.py,第 714 行 如果我不使用 S3 或 S3N 作为 URI 前缀:它可以在本地工作(我可以读取镶木地板数据)。在 Lambda 环境中,我在 pyarrow/parquet.py 的第 848 行中得到了相同的 OSError: Passed non-file path: s3://mybucket/path/to/myfile

我的问题是:

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

谢谢!

【问题讨论】:

【参考方案1】:

AWS 有一个项目 (AWS Data Wrangler) 允许它完全支持 Lambda 层。

在文档中有一个step-by-step 可以做到这一点。

代码示例:

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://...")

Reference

【讨论】:

【参考方案2】:

我能够使用 fastparquet 将 parquet 文件写入 S3。这有点棘手,但当我意识到要将所有依赖项放在一起时,我的突破就来了,我必须使用与 Lambda 使用的完全相同的 Linux。

我是这样做的:

1。使用与 Lambda 一起使用的 Amazon Linux 映像启动 EC2 实例

来源: 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

注意:您可能需要安装许多软件包并将 python 版本更改为 3.6,因为此 Linux 不适用于开发。以下是我寻找包裹的方式:

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 的更好方法,请分享。

来源: Write parquet from AWS Kinesis firehose to AWS S3

【讨论】:

对于 pyarrow 的 many-linux 变体,如果您只保留所有 *16 文件,则为每个 lib 删除其他较大的副本,然后将它们重新打包成一个 zip 文件,lambda 包大小来AWS lambda 接受的低于 250【参考方案3】:

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

【讨论】:

你能提供更多关于你是如何工作的信息吗?即使 pyarrow 包在我的 zip 中,我仍然会遇到 ImportError。它一直在说pyarrow is required for parquet support 我在 Python 2.7 上运行,所以这可能是问题所在。 可能是,但没有上下文很难诊断。不过,您的错误看起来不像 ModuleNotFoundError 或 ImportError 。我按照我提供的链接来创建我的环境。大致:docker run -it lambci/lambda:build-python3.6 bash mkdir lambda cd 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 . [get the lambda.zip locally] zip -ur ../lambda.zip lambda_function.py 感谢@Ptah 的回复。我猜测这是与 AWS Lambda 中的 Python 2.7 运行时不兼容,我是对的。一旦我升级代码以在 3.6 上运行并构建升级后的 zip 文件 pyarrow 就可以正常工作。希望这可以帮助其他遇到此问题的人。 你能给我们一个代码示例吗?我想知道你是如何编写文件和使用 s3fs 对象的......我正在尝试使用 pyarrow.parquet.write_table() 但它没有发生在我身上。谢谢!【参考方案4】:

也可以通过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.使用容器构建

Docker 需要在运行sam build 命令时使用选项--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,它们适用于 Mac、Linux 和 Windows。你有任何错误吗?

以上是关于使用 AWS Lambda (Python 3) 读取存储在 S3 中的 Parquet 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Python 3.6 将 pymysql 模块安装到 AWS Lambda [重复]

AWS Lambda Python 3.7:无法导入模块'lambda_function':缺少必需的依赖项['numpy']

AWS Lambda 上的 Headless Chrome Python 3.8 - 意外退出。状态码是:127

python中的AWS Lambda导入模块错误

python 使用AWS Lambda存取Google表格

如何使用 Python 检索 AWS Lambda 公共 IP 地址?