首页 > 解决方案 > AWS Lambda 函数可以直接使用 s3 上的文件还是需要移动到 /tmp/?

问题描述

我正在尝试在 Python 中编写一个 AWS lambda 函数,以从 s3 存储桶中收集一堆 csv 文件,将它们连接起来,删除重复项并将结果写回 s3。我要读取的文件以前缀/存储在 s3 上的文件夹中。目前我正在尝试使用以下方法一一读取文件:

resp = s3.list_objects_v2(Bucket='mybucket')
#getting all objects in the bucket in a list
for obj in resp['Contents']:
    keys.append(obj['Key'])
#filtering those that are parsed entries
files = [k[6:] for k in keys if 'links/links' in k]
#reading into combined list
for file in files:
    with open(file, 'r') as csvfile:
        reader = csv.reader(csvfile)
        links = links + list(reader)

目前我收到以下错误:

{
  "errorMessage": "[Errno 2] No such file or directory: 'links2020-02-27 14:59:49.933074.csv'",
  "errorType": "FileNotFoundError",
  "stackTrace": [
    "  File \"/var/task/handler.py\", line 21, in concatenatelinks\n    with open(file, 'r') as csvfile:\n"
  ]
}

在早期版本中,我没有对文件名进行切片,这导致了同样的错误。那么我是否需要将所有文件加载到 /tmp/ 中, s3.meta.client.upload_file('/tmp/' + str(filename), bucket, 'fusedlinks/' + str(filename))以便让 lamda 函数可以访问它们,或者是否有更优雅的解决方案?

标签: pythonamazon-web-servicesaws-lambdaboto3

解决方案


从错误看来,文件名约定不正确:links2020-02-27 14:59:49.933074.csv. 通过 boto3 客户端读取文件时,您可能需要转义“空白”。

但是读取文件有两个选项,我个人更喜欢选项2(但取决于内存使用情况):

  1. 一种将文件系统用作 /tmp

您可以参考AWS 文档中提到的示例示例

此外,AWS Lambda 目前提供的 /tmp 大小为 512 MB,如果所有文件的总大小超过 512 MB,您将需要找到不同的解决方案。参考AWS Lambda 限制

  1. 第二种选择是使用 In-memory buffer。您可以使用:Python 的BytesIo。下面的例子:
    def load_from_s3(bucket, path):
        s3_resource = boto3.resource('s3')
        with BytesIO() as data:
            s3_resource.Bucket(bucket).download_fileobj(path, data)
            data.seek(0)
            # Do something with your data in file


推荐阅读