【发布时间】:2021-09-23 09:36:00
【问题描述】:
我在 S3 上将一堆 CSV 文件压缩为一个 zip。我只需要使用 AWS lambda 函数处理 zip 中的一个 CSV 文件
import boto3
from zipfile import ZipFile
BUCKET = 'my-bucket'
s3_rsc = boto3.resource('s3')
def zip_stream(zip_f='app.zip', bkt=BUCKET, rsc=s3_rsc):
obj = rsc.Object(
bucket_name=bkt,
key=zip_f
)
return ZipFile(BytesIO(obj.get()['Body'].read()))
zip_obj = zip_stream()
csv_dat = zip_obj.read('one.csv')
上面的 sn-p 可以很好地处理测试 zip 文件,但是如果 zip 文件大小超过 0.5G,它会失败并出现 内存错误。
错误信息
{ "errorMessage": "", "errorType": "MemoryError", "stackTrace": [ " 文件 "/var/task/lambda_function.py", 第 12 行, 在处理程序中\n all_files = files_in_zip()\n", " 文件 "/var/task/lambda_function.py", 第 36 行, 在 files_in_zip\n zippo = zip_stream()\n", " File "/var/task/lambda_function.py", line 32, in zip_stream\n return ZipFile(BytesIO(obj.get()['Body'].read()))\n", " 文件 "/var/runtime/botocore/response.py",第 77 行,在 read\n chunk = self._raw_stream.read(amt)\n", " File "/var/runtime/urllib3/response.py", line 515, in read\n data = self._fp.read() if not fp_closed else b""\n", " 文件 "/var/lang/lib/python3.8/http/client.py", 第 468 行, 在 read\n s = self._safe_read(self.length)\n", " 文件 "/var/lang/lib/python3.8/http/client.py",第 609 行,在 _safe_read\n data = self.fp.read(amt)\n" ] }
是否有stream/lazyload zipfile 的选项来缓解内存问题?
注意 - 我还提到了一篇旧帖子 (How can I use boto to stream a file out of Amazon S3 to Rackspace Cloudfiles?),它谈到了流式传输文件而不是 zip
【问题讨论】:
-
还可以考虑简单地为 Lambda 函数配置更多 RAM。
-
您可以考虑使用smart-open 根据需要包装来自 S3 的流式数据工作。
-
@AnonCoward smart-open 似乎没有包装/流式传输 zip 格式的文件,我试图包装 io.BufferedReader(response['Body']) 但未能成功。如果 smart-open 可以处理 zip 格式的文件,你能举个例子吗
-
@jarmod 您可以将 Lambda 函数的 RAM 最多增加到 10G,这是一种解决方法,但是,这对我来说似乎是一个昂贵的举动。
-
不一定贵很多。使用更多 RAM,您将获得相应的更多 CPU 和网络 i/o,因此您的进程可能会运行得更快,因此您将每毫秒支付更多费用,但总持续时间更短。也许尝试aws-lambda-power-tuning 以获得最佳组合。
标签: python amazon-web-services amazon-s3