如何将数据写入 CSV 格式的字符串(而不是文件) ?

我想将 [1,2,'a','He said "what do you mean?"']这样的数据转换为 CSV 格式的字符串。

通常人们会使用 csv.writer(),因为它处理所有疯狂的边缘情况(逗号转义,引号转义,CSV 方言,等等)的问题是,csv.writer()希望输出到一个文件对象,而不是一个字符串。

我目前的解决方案是这个有点粗糙的函数:

def CSV_String_Writeline(data):
class Dummy_Writer:
def write(self,instring):
self.outstring = instring.strip("\r\n")
dw = Dummy_Writer()
csv_w = csv.writer( dw )
csv_w.writerow(data)
return dw.outstring

有人能给出一个更优雅的解决方案,仍然处理边缘情况良好?

编辑: 我是这样结束的:

def csv2string(data):
si = StringIO.StringIO()
cw = csv.writer(si)
cw.writerow(data)
return si.getvalue().strip('\r\n')
134939 次浏览

你可以用 StringIO代替你自己的 Dummy_Writer:

这个模块实现了一个类似文件的类 StringIO,它读写字符串缓冲区(也称为内存文件)。

还有 cStringIO,它是 StringIO类的一个更快的版本。

在 Python 3中:

>>> import io
>>> import csv
>>> output = io.StringIO()
>>> csvdata = [1,2,'a','He said "what do you mean?"',"Whoa!\nNewlines!"]
>>> writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC)
>>> writer.writerow(csvdata)
59
>>> output.getvalue()
'1,2,"a","He said ""what do you mean?""","Whoa!\nNewlines!"\r\n'

对于 Python 2,有些细节需要稍作修改:

>>> output = io.BytesIO()
>>> writer = csv.writer(output)
>>> writer.writerow(csvdata)
57L
>>> output.getvalue()
'1,2,a,"He said ""what do you mean?""","Whoa!\nNewlines!"\r\n'

这个版本适用于 utf-8。Csvline2string 表示一行,末尾没有换行符,csv2string 表示许多行,带有换行符:

import csv, io


def csvline2string(one_line_of_data):
si = BytesIO.StringIO()
cw = csv.writer(si)
cw.writerow(one_line_of_data)
return si.getvalue().strip('\r\n')


def csv2string(data):
si = BytesIO.StringIO()
cw = csv.writer(si)
for one_line_of_data in data:
cw.writerow(one_line_of_data)
return si.getvalue()
import csv
from StringIO import StringIO
with open('file.csv') as file:
file = file.read()


stream = StringIO(file)


csv_file = csv.DictReader(stream)

总而言之,我发现答案有点令人困惑:

import csv, io


def csv2string(data):
si = io.BytesIO()
cw = csv.writer(si)
cw.writerow(data)
return si.getvalue().strip('\r\n')


data=[1,2,'a','He said "what do you mean?"']
print csv2string(data)

由于我经常使用这种方法将结果从 疯子异步传回给用户作为 csv 数据,因此我为 巨蟒3编写了以下代码片段。

该代码片段允许您重复使用相同的 StringIo 缓冲区。


import csv
from io import StringIO




class ArgsToCsv:
def __init__(self, seperator=","):
self.seperator = seperator
self.buffer = StringIO()
self.writer = csv.writer(self.buffer)


def stringify(self, *args):
self.writer.writerow(args)
value = self.buffer.getvalue().strip("\r\n")
self.buffer.seek(0)
self.buffer.truncate(0)
return value + "\n"

例如:

csv_formatter = ArgsToCsv()


output += csv_formatter.stringify(
10,
"""
lol i have some pretty
"freaky"
strings right here \' yo!
""",
[10, 20, 30],
)

查看 github gist 的进一步用法: 来源及测试