1

我正在尝试用 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()
4

1 回答 1

6

ZipFile问题是您在调用它之前尝试使用它的内容close

正如文档所说:

您必须致电close()……否则将不会写入重要记录。

最重要的是,虽然它有时有效,但实际上调用getvalue()已关闭的StringIO. 同样,来自文档

在调用对象的方法str之前的任何时间返回包含缓冲区全部内容的 a。StringIOclose()

最后,如果您使用的是 Python 3.x,您可能希望使用BytesIO而不是StringIO. 事实上,您BytesIO甚至可能希望在 2.x 中使用,只要您使用的是 2.6+。


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:
于 2013-06-26T00:33:59.687 回答