【问题标题】:How to create a zip file in memory with a list of PIL image objects?如何使用 PIL 图像对象列表在内存中创建 zip 文件?
【发布时间】:2020-08-16 16:35:23
【问题描述】:

我正在尝试在内存中创建一个包含 PIL 图像对象列表的 zip 文件。

import io
from PIL import Image

def get_images(path):
    '''This returns a list of PIL images'''
    pass


def file_process_im_memory():
    images = get_images('mypath')
    file_object = io.BytesIO()
    file_object2 = io.BytesIO()
    images[0].save(file_object, 'PNG')
    images[1].save(file_object2, 'PNG')
    file_object.seek(0)
    file_object2.seek(0)

图像写入内存,现在我想从内存中的图像文件创建一个 zip 文件,我在下面尝试过,但没有成功。

zip_file = ZipFile(zip_file_bytes_io, 'w')
for image in images:
    file_object = io.BytesIO()
    image.save(file_object, 'PNG')
    file_object.seek(0)
    zip_file.writestr(file_object.getvlaue())
zip_file_bytes_io.seek(0)

【问题讨论】:

    标签: python zip python-imaging-library zipfile in-memory


    【解决方案1】:

    我相信这会如你所愿。正如我在现已删除的评论中所说,一个问题是zip_file.writestr() 的第一个参数应该是文件名/成员名,它将在存档中给出,第二个参数是要写入的数据。

    为了能够做到这一点,必须保留图像文件名。在下面的代码中,get_images() 现在返回了一个 [<image file name>, <PIL image object>] pairs 值列表,因此在写入内存 zip 文件时可以使用该名称。

    #!/usr/bin/env python3
    # https://stackoverflow.com/questions/63439403/how-to-create-a-zip-file-in-memory-with-a-list-of-pil-image-objects
    
    import io
    import os
    from PIL import Image
    from pprint import pprint
    from zipfile import ZipFile
    
    
    def get_images(path):
        """ Returns a list of image file base name & PIL image object pairs. """
    
        # Harcoded with two images for testing purposes.
        IMAGES = (r"C:\vols\Files\PythonLib\Stack Overflow\cookie_cutter_background.png",
                  r"C:\vols\Files\PythonLib\Stack Overflow\Flying-Eagle.png")
    
        images = []
        for image_path in IMAGES:
            # Get image file name without extension.
            image_name = os.path.splitext(os.path.os.path.basename(image_path))[0]
            pil_image = Image.open(image_path)
            images.append([image_name, pil_image])
    
        return images
    
    
    def file_process_in_memory():
        """ Converts PIL image objects into BytesIO in-memory bytes buffers. """
    
        images = get_images('mypath')
    
        for i, (image_name, pil_image) in enumerate(images):
            file_object = io.BytesIO()
            pil_image.save(file_object, "PNG")
            pil_image.close()
            images[i][1] = file_object  # Replace PIL image object with BytesIO memory buffer.
    
        return images  # Return modified list.
    
    
    images = file_process_in_memory()
    
    # Create an in-memory zip file from the in-memory image file data.
    zip_file_bytes_io = io.BytesIO()
    
    with ZipFile(zip_file_bytes_io, 'w') as zip_file:
        for image_name, bytes_stream in images:
            zip_file.writestr(image_name+".png", bytes_stream.getvalue())
    
        pprint(zip_file.infolist())  # Print final contents of in memory zip file.
    
    print('done')
    

    样本输出:

    [<ZipInfo filename='cookie_cutter_background.png' filemode='?rw-------' file_size=727857>,
     <ZipInfo filename='Flying-Eagle.png' filemode='?rw-------' file_size=462286>]
    done
    

    【讨论】:

    • 我尝试通过将创建的 zip 文件写入磁盘来验证上述代码似乎文件已损坏,也许我做错了什么。 with open('tmp.zip', 'wb') as f: f.write(zip_file_bytes_io.read())
    • 那是因为你做错了——使用f.write(zip_file_bytes_io.getvalue())
    • 使用 f.write(zip_file_bytes_io.getvalue()) 无法正确写入 zip 文件,导致 zip 文件损坏
    • 当我测试它时它对我有用(在我发表评论建议使用getvalue()之前) - 所以肯定有其他问题。您如何确定创建的文件已损坏?
    • 解压文件或直接打开文件
    猜你喜欢
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-23
    • 2020-01-03
    • 2014-06-30
    相关资源
    最近更新 更多