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

Posted

技术标签:

【中文标题】如何将数据作为字符串(不是文件)写入 CSV 格式?【英文标题】:How do I write data into CSV format as string (not file)? 【发布时间】:2012-02-27 18:18:29 【问题描述】:

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

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

我目前的解决方案是这个有点 hacky 的功能:

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')

【问题讨论】:

在 Python 3 中,StringIO()io 库中。 因为 "\r" 和 "\n" 被认为是空白,你实际上可以只使用不带参数的 "strip":return si.getvalue().strip()--除非出于某种原因你需要在结束。 【参考方案1】:

您可以使用StringIO 代替您自己的Dummy_Writer

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

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

【讨论】:

cStringIO 自 python 3.0 起就消失了。请改用io.StringIO【参考方案2】:

在 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'

【讨论】:

应该是output = StringIO.StringIO()io.StringIO() 会引发 TypeError: string argument expected, got 'str'。 @Marboni: StringIO 在 Python 3 中消失了(这是我的解决方案所用的),我无法在 Python 2.7.3 中重现该错误 - 尽管我在writer.writerow(...) 行 (unicode argument expected, got 'str')。将对此进行调查。 @Marboni:感谢您的提醒:我在 *** 的帮助下found the problem。在 Python 2 中,您需要 io.BytesIO() 而不是 io.StringIO() @Marboni:在 Python 2.7.9 中,它适用于 StringIO.StringIO() 或 io.BytesIO()。 @nz_21:我刚刚重新测试了它——工作得很好。当然,第二个示例(为 Python 2 编写,如明确说明的那样)会抛出该错误。【参考方案3】:

这是适用于 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()

【讨论】:

【参考方案4】:
import csv
from StringIO import StringIO
with open('file.csv') as file:
    file = file.read()

stream = StringIO(file)

csv_file = csv.DictReader(stream)

【讨论】:

不鼓励仅使用代码的答案,您应该在答案中添加一些说明【参考方案5】:

我找到了答案,总而言之,有点令人困惑。对于 Python 2,这种用法对我有用:

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)

【讨论】:

【参考方案6】:

由于我经常使用这种方法将结果从 sanic 异步传输回用户作为 csv 数据,因此我为 Python 3 编写了以下 sn-p。 p>

sn-p 让您可以反复重用相同的 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 上查看更多用法:source and test

【讨论】:

以上是关于如何将数据作为字符串(不是文件)写入 CSV 格式?的主要内容,如果未能解决你的问题,请参考以下文章

如何将火花数据输出到具有单独列的 csv 文件?

如何使用Nodejs将数据作为文件夹中的文件名写入CSV文件

python存储数据的操作(csv格式文件,Excel表格文件)!!!

如何将多个csv按行合并?(不是首尾相接的按列合并)

将 utf-8 格式的 Python 列表写入 CSV

如何将数据作为列写入熊猫