如何从 ZipFile 进行流式传输?如何“即时”拉链?

Put*_*nik 7 python zip stream aws-lambda

我想压缩一个流并输出结果。我正在使用 AWS Lambda 来完成此操作,这对于可用磁盘空间和其他限制很重要。如果重要的话,我将使用压缩流使用upload_fileobj()或 来编写 AWS S3 对象。put()

我可以创建一个存档作为文件,直到我有小对象:

import zipfile
zf = zipfile.ZipFile("/tmp/byte.zip", "w")
zf.writestr(filename, my_stream.read())
zf.close()
Run Code Online (Sandbox Code Playgroud)

对于大量数据,我可以创建一个对象而不是文件:

from io import BytesIO
...
byte = BytesIO()
zf = zipfile.ZipFile(byte, "w")
....
Run Code Online (Sandbox Code Playgroud)

但如何将压缩流传递到输出?如果我使用zf.close()- 流将被关闭,如果我不使用它 - 存档将不完整。

Mic*_*mza 11

您可以使用stream-zip,而不是使用Python内置的zipfile (完全公开:由我编写)

例如,如果您有一个字节的可迭代对象,my_data_iter您可以使用其函数获取 zip 文件的可迭代对象stream_zip

from datetime import datetime
from stream_zip import stream_zip, ZIP_64

def files():
    modified_at = datetime.now()
    perms = 0o600
    yield 'my-file-1.txt', modified_at, perms, ZIP_64, my_data_iter

my_zip_iter = stream_zip(files())
Run Code Online (Sandbox Code Playgroud)

如果您需要一个压缩字节的类似文件的对象,比如说传递给 boto3 的 upload_fileobj,您可以使用转换函数从可迭代对象进行转换,就像从to-file-like-obj转换一样(也是我写的)

import boto3
from to_file_like_obj import to_file_like_obj

# Convert iterable to file-like object
my_file_like_obj = to_file_like_obj(my_zip_iter)

# Upload to S3 (likely using a multipart upload)
s3 = boto3.client('s3')
s3.upload_fileobj(my_file_like_obj, 'my-bucket', 'my.zip')
Run Code Online (Sandbox Code Playgroud)

  • 感谢您编写这个库,非常有帮助,正是我正在寻找的! (2认同)

meu*_*euh 4

您可能想尝试zipfile 的zipstream版本。例如,要将 stdin 作为 zip 文件压缩到 stdout,并将数据保存为TheLogFile使用迭代器命名的文件:

#!/usr/bin/python3
import sys, zipstream
with zipstream.ZipFile(mode='w', compression=zipstream.ZIP_DEFLATED) as z:
    z.write_iter('TheLogFile', sys.stdin.buffer)
    for chunk in z:
        sys.stdout.buffer.write(chunk)
Run Code Online (Sandbox Code Playgroud)