【问题标题】:Using csv.writer to write a string to StringIO, why does it add extra characters?使用 csv.writer 向 StringIO 写入字符串,为什么会添加额外的字符?
【发布时间】:2016-02-19 20:30:07
【问题描述】:

当我将此字符串写入 StringIO 时,格式如何改变?

header = '\r\n'.join(
    [unicode(line,'utf8') for line in 
     ['"Text"',
    '"More Text"',
     '',]])
print header

输出:

"Text"
"More Text"

现在将它添加到我的 StringIO:

si = StringIO.StringIO()

writer = csv.writer(si)
writer.writerow(header))

si.getvalue()

输出:

'"""",T,e,x,t,"""","\r","\n","""",M,o,r,e, ,T,e,x,t,"""","\r","\n"\r\n'

为什么要添加逗号和额外的" 字符?

【问题讨论】:

  • 这是因为 header 已经是一个字符串,然后你循环它的字符,所以只需删除 for 循环并将 header 直接写入文件
  • @SirParselot 我明白了,我的非 StringIO 代码工作的原因是因为它写入的所有字符之间都带有换行符,但是一旦我写入 .csv,换行符都会消失。我正在用我的新问题编辑我的问题...
  • 不,我的意思是for line in header 循环。 header 是一个字符串,因此循环遍历它会给你每个字符,所以line 真的是一个字符
  • @SirParselot 抱歉,由于我之前的示例,现在一切都令人困惑。让我删除它。第二个代码块本身没有for 循环,但仍然写得很有趣。
  • 好吧,我不知道额外的引号,但您可以通过在标题周围添加 [] 来解决大部分问题,因为它需要一个列表

标签: python python-2.7 csv


【解决方案1】:

那是因为writer.addrow 需要一个包含元素的可迭代对象,并且字符串也是一个可迭代对象。

即这段代码:

l = [1,2,3]
for i in l:
    print i

将打印:

1
2
3

同样的原则也适用于字符串:

s = 'abc'
for c in s:
    print c

将打印:

a
b
c

最后,

writer.writerow([1,2,3])   # Gives you 1,2,3
writer.writerow('abc')     # Gives you a,b,c

由于header 在您的示例中是一个字符串,因此其中的每个字符都被视为单独的行。但是,这会导致正确的行:

writer.writerow(['abc'])   # Gives you abc

最后,当某些元素中有分隔符时,许多 csv 方言使用引号,即这里第一个逗号不被视为分隔符,因为它位于引号内:

writer.writerow(['a,b',3])    # Gives you "a,b",3

当引号字符本身出现在元素中时,它也必须被转义,以免混淆解析器。如果启用Dialect.doublequote 标志,csv writer 将简单地将其加倍:

writer.writerow(['a",b',3])    # "a"",b",3

【讨论】:

  • 你知道为什么它是双引号吗?
  • @SirParselot:许多 CSV 方言对带有空格的元素使用引号,即:"1 2",3,"3 4 5"。因此,将它们加倍是一种在已经用引号转义的字符串中转义引号字符的方法。它在文档中提到:docs.python.org/2/library/csv.html#csv.Dialect.doublequote
  • 嗯,有道理。由于没有空格,所以我没有注意到。
  • 现在一切都变得有意义了。我是 CSV 的新手,我花了足够长的时间才能让它工作,只是为了让我的 DataFrame 使用自定义标题正确写入。然后尝试让相同的代码为 StringIO 工作,但没有任何意义。
猜你喜欢
  • 2020-11-25
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-30
相关资源
最近更新 更多