代码之家  ›  专栏  ›  技术社区  ›  John B

python内存zip库

  •  48
  • John B  · 技术社区  · 14 年前

    是否有一个python库允许在内存中操作zip存档,而不必使用实际的磁盘文件?

    zipfile库不允许您更新存档。唯一的方法似乎是将其提取到一个目录中,进行更改,并从该目录创建一个新的zip。我想在没有磁盘访问权限的情况下修改zip文件,因为我将下载它们,进行更改,然后再次上载它们,所以我没有理由存储它们。

    类似Java的ZIPuntStudio/ZIPOuttStudio的东西会起到作用,尽管任何接口都可以避免磁盘访问。

    4 回复  |  直到 7 年前
        1
  •  70
  •   Jason R. Coombs    8 年前

    根据 Python docs :

    class zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])
    
      Open a ZIP file, where file can be either a path to a file (a string) or a file-like object. 
    

    因此,要在内存中打开文件,只需创建一个类似文件的对象(可能使用 BytesIO )

    file_like_object = io.BytesIO(my_zip_data)
    zipfile_ob = zipfile.ZipFile(file_like_object)
    
        2
  •  40
  •   Justin Ethier    11 年前

    从文章 In-Memory Zip in Python :

    下面是我2008年5月关于用python压缩内存的帖子,自从posterous关闭后重新发布。

    我最近注意到有一个付费组件可用于使用python压缩内存中的文件。考虑到这应该是免费的,我将下面的代码组合在一起。它只经过了非常基本的测试,所以如果有人发现任何错误,请告诉我,我会更新这个。

    import zipfile
    import StringIO
    
    class InMemoryZip(object):
        def __init__(self):
            # Create the in-memory file-like object
            self.in_memory_zip = StringIO.StringIO()
    
        def append(self, filename_in_zip, file_contents):
            '''Appends a file with name filename_in_zip and contents of 
            file_contents to the in-memory zip.'''
            # Get a handle to the in-memory zip in append mode
            zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)
    
            # Write the file to the in-memory zip
            zf.writestr(filename_in_zip, file_contents)
    
            # Mark the files as having been created on Windows so that
            # Unix permissions are not inferred as 0000
            for zfile in zf.filelist:
                zfile.create_system = 0        
    
            return self
    
        def read(self):
            '''Returns a string with the contents of the in-memory zip.'''
            self.in_memory_zip.seek(0)
            return self.in_memory_zip.read()
    
        def writetofile(self, filename):
            '''Writes the in-memory zip to a file.'''
            f = file(filename, "w")
            f.write(self.read())
            f.close()
    
    if __name__ == "__main__":
        # Run a test
        imz = InMemoryZip()
        imz.append("test.txt", "Another test").append("test2.txt", "Still another")
        imz.writetofile("test.zip")
    
        3
  •  19
  •   Anthon    8 年前

    ethier提供的示例有几个问题,其中一些主要问题是:

    • 对windows上的真实数据不起作用。zip文件是二进制文件,其数据应始终使用打开的“wb”文件写入
    • 对每个文件都附加zip文件,这是低效的。它可以作为一个 InMemoryZip 属性
    • 文档说明应该显式地关闭zip文件,这不是在append函数中完成的(它可能工作(例如),因为zf超出了范围,并且关闭了zip文件)
    • 为zipfile中的所有文件设置create_system标志 每一个 追加文件的时间,而不是每个文件仅追加一次。
    • 在python<3上,cstringio比stringio高效得多
    • 在Python3上不起作用(最初的文章是在3.0发布之前的,但是在发布代码时3.1已经发布了很长时间)。

    如果您安装了 ruamel.std.zipfile (其中我是作者)。后

    pip install ruamel.std.zipfile
    

    或者包括 here ,您可以:

    import ruamel.std.zipfile as zipfile
    
    # Run a test
    zipfile.InMemoryZipFile()
    imz.append("test.txt", "Another test").append("test2.txt", "Still another")
    imz.writetofile("test.zip")  
    

    您也可以使用 imz.data 去任何你需要的地方。

    您也可以使用 with 语句,如果提供文件名,则在离开该上下文时将写入zip的内容:

    with zipfile.InMemoryZipFile('test.zip') as imz:
        imz.append("test.txt", "Another test").append("test2.txt", "Still another")
    

    由于延迟写入光盘,您实际上可以从旧的 test.zip 在这种情况下。

        4
  •  6
  •   Vladimir    7 年前

    Python 3

    import io
    import zipfile
    
    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
        for file_name, data in [('1.txt', io.BytesIO(b'111')), ('2.txt', io.BytesIO(b'222'))]:
            zip_file.writestr(file_name, data.getvalue())
    with open('C:/1.zip', 'wb') as f:
        f.write(zip_buffer.getvalue())