【问题标题】:python: zipping csv bufferspython:压缩 csv 缓冲区
【发布时间】:2023-03-06 19:17:02
【问题描述】:

我想将一些 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())

不知道为什么,但这让它起作用了

【问题讨论】:

    标签: python django python-2.7 csv zipfile


    【解决方案1】:

    所以,您似乎没有正确编码您的 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,它对 Unicode 的处理能力比 Python 2 好得多。

    【讨论】:

    • 感谢您的回答。 UnicodeWriter 仍然没有成功。 CSV 缓冲区现在可以了,但如果我尝试压缩它,它会以某种方式损坏。如果我用十六进制转储解压缩的 CSV,我会得到 00000000: 0000 0000 0000 0000 0000 0000 0000 ......
    • 如果我尝试相同,但写入文件而不是缓冲区,一切正常。这可能是一种解决方法,但我仍然想使用缓冲区而不是磁盘上的文件。这可能是什么问题??
    • 我刚刚尝试将您的 zipped_file 保存到磁盘上的一个文件中(使用 f.write(zipped_file.getvalue())),该文件是一个非常好的 zip 文件,里面有一个非常好的 CSV(使用 UTF- 8 个编码文本)。这告诉我问题出在您在问题中省略的应用程序部分的某个地方 - 您确定 Django 正确读取并提供此缓冲区吗?
    • 感谢 randomir 提供这条线索!我尝试了相同的方法(写入磁盘而不是作为下载),并且成功了!所以正如你所建议的,问题应该是 Django 没有正确地提供缓冲区。再次感谢,我接受了你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    相关资源
    最近更新 更多