Python内存中的zip库
有没有一个Python库允许在内存中操作zip存档,而不必使用实际的磁盘文件?Python内存中的zip库
zip文件库不允许您更新存档。唯一的办法似乎是将其解压缩到一个目录中,进行更改,然后从该目录创建一个新的压缩文件。我想在没有磁盘访问的情况下修改zip存档,因为我将下载它们,进行更改并再次上传,因此我没有理由存储它们。
东西类似于Java的ZipInputStream/ZipOutputStream会做的伎俩,虽然所有,任何接口避免了磁盘访问就可以了。
按照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)
很酷谢谢。虽然,我想你想让最后一个变量被称为别的东西,比如'the_zip_file'。否则这不会编译 – Kirby 2016-03-15 20:09:15
@Kirby你是对的。如果代码位于脚本的全局变量中,该代码就可以工作,但在函数中,'zipfile'只能是本地代码。接得好。 – 2016-03-23 13:52:17
@ JasonR.Coombs:它会以某种方式工作,但不是真的。即使在脚本的全局部分,它也会覆盖“zipfile”模块,从而无法在脚本中稍后使用“zipfile”模块。所以它只会在全局部分处理一个zip文件的情况下才起作用。 – vog 2016-03-31 13:22:45
下面是我从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")
有用的链接 - 这是一个很好的例子,说明如何用Jason的答案描述的方式使用ZipFile对象。谢谢 – 2010-03-17 16:59:34
没问题,很高兴你觉得它有用。 – 2010-03-17 17:01:09
小心点总结这里链接的内容,如果它死了,你的回答也是如此 – 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
读取。
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())
OK,我知道我错了关于zip文件毕竟。感谢大家。 – 2010-03-17 17:00:20