我想将一些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())
不知道为什么,但这使它发挥作用
答案 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。