使用 Lambda 从 S3 上的 CSV 文件在 S3 上创建一个 zip 文件

问题描述

每天在我的 S3 存储桶中生成大约 60 个 CSV 文件。每个文件的平均大小约为 500MB。我想通过 lambda 函数动态压缩所有这些文件(无需在 Lambda 执行中下载文件)并将这些压缩文件上传到另一个 s3 存储桶。我遇到了这些解决方12,但我在实施中仍然遇到问题。现在,我正在尝试将 CSV 文件数据流式传输到一个压缩文件中(这个 zip 文件是在 Lambda tmp 目录中创建的),然后上传到 s3。但是我在写入 zip 文件时收到此错误消息: [Errno 36] File name too long

这是我的测试 Lambda 函数,我只是尝试使用一个文件,但在实际情况下,我需要单独压缩 50-60 个 CSV 文件

import boto3
import zipfile


def lambda_handler(event,context):
    s3 = boto3.resource('s3')
    iterator = s3.Object('bucket-name','file-name').get()['Body'].iter_lines()
    my_zip = zipfile.ZipFile('/tmp/test.zip','w')
    for line in iterator:
        my_zip.write(line)
    
    s3_resource.Meta.client.upload_fileobj(file-name,"another-bucket-name","object-name") 

另外,有没有一种方法可以让我从我的 CSV 文件中流式传输数据,将其压缩并将其上传到另一个 s3 存储桶,而无需在 Lambda 内存上实际保存完整的 zip 文件

解决方法

经过大量研究和试验,我能够让它发挥作用。我为我的问题使用了 smart_open 库,并设法压缩了 550MB 的文件,而我的 Lambda 中仅使用了 150MB 的内存。要使用外部库,我必须在 Lambda 中使用 Layers。这是我的代码:

from smart_open import open,register_compressor
import lzma,os


def lambda_handler(event,context):
    with open('s3://bucket-name-where-large-file/file-key-name') as fin:
        with open('s3://bucket-name-to-put-zip-file/zip-file-key-name','w') as fout:
            for line in fin:
                fout.write(line)

请注意,smart_open 支持 .gz.bz2 文件压缩。如果您想以其他格式压缩文件,您可以使用此库的 register_compressor 方法创建您自己的压缩器。