【问题标题】:How do I write data into CSV format as string (not file)?如何将数据作为字符串(不是文件)写入 CSV 格式?
【发布时间】: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()--除非出于某种原因你需要在结束。

标签: python string csv


【解决方案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:感谢您的提醒:我在 StackOverflow 的帮助下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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-28
        • 2019-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-16
        相关资源
        最近更新 更多