Python内存中的zip库

问题描述:

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

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

东西类似于Java的ZipInputStream/ZipOutputStream会做的伎俩,虽然所有,任何接口避免了磁盘访问就可以了。

+1

OK,我知道我错了关于zip文件毕竟。感谢大家。 – 2010-03-17 17:00:20

按照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) 
+1

很酷谢谢。虽然,我想你想让最后一个变量被称为别的东西,比如'the_zip_file'。否则这不会编译 – Kirby 2016-03-15 20:09:15

+0

@Kirby你是对的。如果代码位于脚本的全局变量中,该代码就可以工作,但在函数中,'zipfile'只能是本地代码。接得好。 – 2016-03-23 13:52:17

+0

@ JasonR.Coombs:它会以某种方式工作,但不是真的。即使在脚本的全局部分,它也会覆盖“zipfile”模块,从而无法在脚本中稍后使用“zipfile”模块。所以它只会在全局部分处理一个zip文件的情况下才起作用。 – vog 2016-03-31 13:22:45

从文章In-Memory Zip in Python

下面是我从2008年五月,在内存与Python,重贴,因为Posterous正在关闭荏苒一个职位。

我最近发现,可用于内存与Python的zip文件的付费部分。考虑到这是应该是免费的,我把以下代码放在一起。它只经过了非常基本的测试,所以如果有人发现任何错误,请告诉我,我会更新它。

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

有用的链接 - 这是一个很好的例子,说明如何用Jason的答案描述的方式使用ZipFile对象。谢谢 – 2010-03-17 16:59:34

+0

没问题,很高兴你觉得它有用。 – 2010-03-17 17:01:09

+0

小心点总结这里链接的内容,如果它死了,你的回答也是如此 – 2013-03-17 12:46:51

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

  • 不适合在Windows真实的数据。的ZIP文件是二进制和它的数据应该总是被写入与文件打开的“Wb”
  • ZIP文件被附加到每个文件,这是低效的。因为ZF超出范围,它可以只被打开并保持为InMemoryZip属性
  • 该ZIP文件应明确关闭,在此不追加功能完成(它可能工作(为例子)的文档状态关闭ZIP文件)
  • 的create_system标志设置为所有文件的zip文件一次文件附加,而不是每个文件只有一次。
  • on Python < 3 cStringIO比StringIO效率更高
  • 在Python 3上无法正常工作(原来的文章来自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读取。

+0

为什么不在Python 2中使用io.BytesIO? – boxed 2016-10-14 13:13:25

+0

@boxed没有什么特别的理由,除了你应该检查2.7上的BytesIO是否使用更快的底层C实现,并且不是Python唯一兼容层调用StringIO(而不是CStringIO) – Anthon 2016-10-17 06:59:08

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