在内存Zip文件Python错误

Mat*_*ern 1 python zip amazon-s3 zipfile stringio

我正在尝试用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()
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 6

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

正如文件所说:

你必须打电话close()......或者不会写出必要的记录.

最重要的是,虽然它有时工作,它实际上是不合法的调用getvalue()上封闭StringIO.再次,从文档:

str在调用StringIO对象的close()方法之前,随时返回包含缓冲区的全部内容的a .

最后,如果你使用的是Python 3.x,你可能想要使用BytesIO而不是StringIO.实际上,BytesIO只要你使用2.6+ ,你甚至可能想要在2.x中使用.


此外,如果您使用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)
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Python 2.x,并希望继续使用StringIO它,则它不能直接用作上下文管理器,因此您必须将第一行替换为:

with contextlib.closing(StringIO()) as zip_file:
Run Code Online (Sandbox Code Playgroud)