python:压缩csv缓冲区

时间:2017-07-05 13:04:19

标签: python django python-2.7 csv zipfile

我想将一些csv缓冲区压缩到一个新的zip缓冲区中,如下所示(python 2.7):

files = []

csv_buffer = StringIO.StringIO()
writer = csv.writer(csv_buffer)
writer.writerow(["some", "csv", "data"])

csv_buffer.seek(0)

files.append(csv_buffer)

zipped_file = io.BytesIO()

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

zipped_file.seek(0)

然后我通过Django视图调度生成的缓冲区进行下载。但是,如果我打开zip,我会找到一个文件(0.csv),但它没有正确编码。我想把它编码为UTF-8。

我也尝试了如下:

zipper.writestr("{}.csv".format(i), csv_file.read().encode("utf-8"))

但这没有任何区别。也在改变

zipped_file = io.BytesIO()

zipped_file = StringIO.StringIO()

没有帮助。 任何关于出了什么问题的想法都会非常感激!

编辑:我的解决方案

尽管下面有其他有用和有趣的答案,我通过改变

来解决问题
    zipper.writestr("{}.csv".format(i), csv_file.read())

     zipper.writestr(zipfile.Zipinfo("foo.csv"), csv_file.read())

不知道为什么,但这使它发挥作用

1 个答案:

答案 0 :(得分:2)

因此,您似乎没有正确编码CSV。

csv module文档(Python 2.7)中查看此注释:

  

注意此版本的csv模块不支持Unicode输入。此外,目前有一些关于ASCII NUL字符的问题。因此,所有输入应为UTF-8或可打印的ASCII以确保安全;请参阅Examples部分中的示例。

这是他们所指的例子:

class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)

只需使用UnicodeWriter代替csv.writer(直接替代):

writer = UnicodeWriter(csv_buffer)

而不是:

writer = csv.writer(csv_buffer)

或者,如果可以的话,切换到Python 3,它比Python 2更好地处理Unicode。