我正在尝试在Python中创建内存中的zip文件并将其上传到Amazon S3。我已经阅读过关于此事的类似帖子,但无论我尝试什么,Windows和Linux(RHEL5)都无法打开它(它已经损坏)。这是我正在运行的代码:
f_redirects = StringIO()
f_links = StringIO()
f_metadata = StringIO()
# Write to the "files"
zip_file = StringIO()
zip = zipfile.ZipFile(zip_file, 'a', zipfile.ZIP_DEFLATED, False)
zip.writestr('redirects.csv', f_redirects.getvalue())
zip.writestr('links.csv', f_bad_links.getvalue())
zip.writestr('metadata.csv', f_metadata.getvalue())
f_redirects.close()
f_links.close()
f_metadata.close()
k = Key(BUCKET)
k.key = '%s.zip' % base_name
k.set_metadata('Content-Type', 'application/zip')
k.set_contents_from_string(zip_file.getvalue())
zip.close()
zip_file.close()
答案 0 :(得分:6)
问题是,您在尝试ZipFile
之前尝试使用close
的内容。
正如the documentation所说:
您必须致电
close()
...或不会写入必要的记录。
最重要的是,虽然它有时会起作用,但在关闭的getvalue()
上调用StringIO
实际上是不合法的。同样,来自the docs:
在调用
str
对象的StringIO
方法之前,随时返回包含缓冲区全部内容的close()
。
最后,如果您使用的是Python 3.x,则可能需要使用BytesIO
而不是StringIO
。事实上,只要您使用2.6 +,即使在2.x中也可以使用BytesIO
。
此外,如果您使用with
语句而不是手动尝试close
事件,那么您的代码将更具可读性且更难出错,并且没有尝试“声明您的顶部的变量“C风格:
with BytesIO() as zip_file:
with zipfile.ZipFile(zip_file, 'a', zipfile.ZIP_DEFLATED, False) as zip:
zip.writestr('redirects.csv', f_redirects.getvalue())
zip.writestr('links.csv', f_bad_links.getvalue())
zip.writestr('metadata.csv', f_metadata.getvalue())
zip_contents = zip_file.getvalue()
k = Key(BUCKET)
k.key = '%s.zip' % base_name
k.set_metadata('Content-Type', 'application/zip')
k.set_contents_from_string(zip_contents)
如果您使用的是Python 2.x,并希望继续使用StringIO
,则它不能直接用作上下文管理器,因此您必须将第一行替换为:
with contextlib.closing(StringIO()) as zip_file: