将多个.CSV文件发送到.ZIP,而不用在Python中存储到磁盘 [英] Sending multiple .CSV files to .ZIP without storing to disk in Python

查看:432
本文介绍了将多个.CSV文件发送到.ZIP,而不用在Python中存储到磁盘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Django网站制作报告应用程式。我想运行多个报告,并让每个报告在内存中生成一个.csv文件,可以批量下载为.zip。我想这样做而不存储任何文件到磁盘。到目前为止,为了生成单个.csv文件,我遵循常见的操作:

I'm working on a reporting application for my Django powered website. I want to run several reports and have each report generate a .csv file in memory that can be downloaded in batch as a .zip. I would like to do this without storing any files to disk. So far, to generate a single .csv file, I am following the common operation:

mem_file = StringIO.StringIO()
writer = csv.writer(mem_file)
writer.writerow(["My content", my_value])
mem_file.seek(0)
response = HttpResponse(mem_file, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=my_file.csv'

这个工作正常,但只适用于一个解压缩的.csv文件。例如,如果我有一个使用StringIO流创建的.csv文件的列表:

This works fine, but only for a single, unzipped .csv. If I had, for example, a list of .csv files created with a StringIO stream:

firstFile = StringIO.StringIO()
# write some data to the file

secondFile = StringIO.StringIO()
# write some data to the file

thirdFile = StringIO.StringIO()
# write some data to the file

myFiles = [firstFile, secondFile, thirdFile]

如何返回一个包含 myFiles 中所有对象的压缩文件,并且可以正确解压缩以显示三个.csv文件?

How could I return a compressed file that contains all objects in myFiles and can be properly unzipped to reveal three .csv files?

推荐答案

zip文件是一个标准库模块,完全按照您的要求。对于你的用例,肉和土豆是一个称为writestr的方法,它接受一个文件的名称和其中包含你想要压缩的数据。

zipfile is a standard library module that does exactly what you're looking for. For your use-case, the meat and potatoes is a method called "writestr" that takes a name of a file and the data contained within it that you'd like to zip.

在下面的代码中,我对文件进行了解压缩时使用了一个顺序命名方案,但是可以随意切换。

In the code below, I've used a sequential naming scheme for the files when they're unzipped, but this can be switched to whatever you'd like.

import zipfile
import StringIO

zipped_file = StringIO.StringIO()
with zipfile.ZipFile(zipped_file, 'w') as zip:
    for i, file in enumerate(files):
        file.seek(0)
        zip.writestr("{}.csv".format(i), file.read())

zipped_file.seek(0)

- 防止您的代码(提示提示Python 3提示提示),您可能需要切换到使用 io .BytesIO 而不是StringIO,因为Python 3都是关于字节的。另一个好处是,在读取之前,io.BytesIO没有必要使用显式寻找(我没有用Django的HttpResponse测试这个行为,所以我在这里留下了最后一个寻找)。

If you want to future-proof your code (hint hint Python 3 hint hint), you might want to switch over to using io.BytesIO instead of StringIO, since Python 3 is all about the bytes. Another bonus is that explicit seeks are not necessary with io.BytesIO before reads (I haven't tested this behavior with Django's HttpResponse, so I've left that final seek in there just in case).

import io
import zipfile

zipped_file = io.BytesIO()
with zipfile.ZipFile(zipped_file, 'w') as f:
    for i, file in enumerate(files):
        f.writestr("{}.csv".format(i), file.getvalue())

zipped_file.seek(0)

这篇关于将多个.CSV文件发送到.ZIP,而不用在Python中存储到磁盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆