Python内存中的zip库

有没有一个Python库,允许操纵内存中的zip档案,而不必使用实际的磁盘文件?

ZipFile库不允许你更新档案。 唯一的办法似乎是提取到一个目录,进行更改,并从该目录中创build一个新的zip。 我想在没有磁盘访问的情况下修改zip档案,因为我将会下载它们,进行更改并重新上传,所以我没有理由保存它们。

类似于Java的ZipInputStream / ZipOutputStream的东西可以做到这一点,尽pipe任何避免磁盘访问的接口都可以。

根据Python文档 :

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. 

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

 file_like_object = io.BytesIO(my_zip_data) zipfile_ob = zipfile.ZipFile(file_like_object) 

从Python中的In-Memory Zip :

下面是我从2008年5月份的一篇关于使用Python进行内存压缩的文章,自Posterous正在closures后重新发布。

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

 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") 

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

  • 不适用于Windows上的实际数据。 一个ZIP文件是二进制的,它的数据应该总是用打开的文件'wb'
  • ZIP文件被追加到每个文件,这是低效的。 它可以打开并保存为InMemoryZip属性
  • 该文档指出,ZIP文件应该显式closures,这不是在附加函数中完成的(它可能工作(例如),因为zf超出了范围,并closuresZIP文件)
  • 每次附加一个文件,而不是每个文件一次,就为zipfile中的所有文件设置create_system标志。
  • 在Python上<3 cStringIO比StringIO效率更高
  • 在Python 3上不起作用(原来的文章是从3.0版本之前发布的,但是在发布代码的时候3.1已经很久了)。

如果您安装了ruamel.std.zipfile (我是其作者),则可以使用更新版本。 后

 pip install ruamel.std.zipfile 

或从这里包括class级的代码,你可以这样做:

 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读取。

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())