在Windows上,Python中的CSV添加了额外的回车符


231
import csv
outfile = file('test.csv', 'w')
writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
writer.writerow(['hi','dude'])
writer.writerow(['hi2','dude2'])
outfile.close()

它会生成文件,每行test.csv都有一个额外的文件\r,如下所示:

test.csv

hi,dude\r\r\nhi2,dude2\r\r\n

而不是预期的:

hi,dude\r\nhi2,dude2\r\n

为什么会发生这种情况,或者这实际上是预期的行为?

注意:

  • Python 2或3可能会发生这种现象。

Answers:


311

Python 3:

with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

在Windows上,在将文件传递到或之前,始终以二进制模式("rb""wb")打开文件。csv.readercsv.writer

尽管该文件是文本文件,但所涉及的库将CSV视为二进制格式,并带有\r\n单独的记录。如果隔板是写在文本模式中,Python运行时替换\n使用\r\n,因此\r\r\n在该文件中观察到的。

请参阅此先前的答案


3
这对于ASCII很好,但是会终止像UTF-8这样的编码。杰森下面的解决方案为我工作。
汤姆(Tom)

66
在Python 3,我可以通过使用文件对象下列选项来解决这个问题:open(..., "w", newline="\n", encoding="utf-8")newline也可以是空白字符串,结果相同。"wb"在Python 3中不起作用,字符串和缓冲区接口不兼容。
CodeManX

优雅的处理额外回车的方法
ForeverLearner,2016年

2
在Python2中不起作用,因此,如果您需要同时兼容2和3,请使用@ jason-r-coombs给出的答案:writer = csv.writer(f, lineterminator='\n')
yossiz74 '18

4
真遗憾,这样的基本,通用和简单的API无法按要求运行
SomethingSomething

248

尽管@ john-machin提供了一个很好的答案,但这并不总是最好的方法。例如,除非您将所有输入编码为CSV编写器,否则它在Python 3上不起作用。另外,如果脚本要使用sys.stdout作为流,它也无法解决问题。

我建议在创建writer时设置'lineterminator'属性:

import csv
import sys

doc = csv.writer(sys.stdout, lineterminator='\n')
doc.writerow('abc')
doc.writerow(range(3))

该示例将在Python 2和Python 3上运行,并且不会产生不需要的换行符。但是请注意,它可能会产生不需要的换行符(在Unix操作系统上省略LF字符)。

但是,在大多数情况下,我认为比将所有CSV视为二进制格式更可取,而且更自然。我提供此答案作为您考虑的替代方法。


6
我认为这是最好的答案。至于在Unix中有问题,如何调用sys.platform并动态处理它呢?
sovemp

4
我认为也是最佳答案,并且lineterminator ='\ n'效果很好。
eikonal 2015年

1
如果您不“将所有输入都编码为CSV编写器”,是否可以举一个出现该问题的示例?
斯蒂芬,

注意:使用此方法\r不再逃脱!看来这是中的错误csvwriter,但就目前而言,输出不合格的CSV意味着这不是可行的方法。
flow2k

^M为我解决了问题,而接受的答案的2条建议不起作用。
user985366

55

在Python 3中(我还没有在Python 2中尝试过),您也可以

with open('output.csv','w',newline='') as f:
    writer=csv.writer(f)
    writer.writerow(mystuff)
    ...

根据文档

在文档的脚注中对此有更多说明

如果未指定newline ='',则嵌入引号中的换行符将无法正确解释,并且在使用\ r \ n linendings的平台上将添加额外的\ r。指定newline =''应该总是安全的,因为csv模块会执行自己的(通用)换行符处理。


2
@ Yibo-Yang,您节省了我很多时间。
1man 16/09/08

4
大。我在python 3.5中证实了这种方式
jef

为什么这不是默认行为?
Marc Stober '18

6

您可以在csv writer命令中引入 lineterminator ='\ n'参数。

import csv
delimiter='\t'
with open('tmp.csv', '+w', encoding='utf-8') as stream:
    writer = csv.writer(stream, delimiter=delimiter, quoting=csv.QUOTE_NONE, quotechar='',  lineterminator='\n')
    writer.writerow(['A1' , 'B1', 'C1'])
    writer.writerow(['A2' , 'B2', 'C2'])
    writer.writerow(['A3' , 'B3', 'C3'])

1
在Python 3.5.2中,这是唯一对我有用的东西(嗯,我只是用了lineterminator='\n');CSV模块似乎是的起源\r\n。没有open任何论据具有任何效果。
汤米

5

我不确定为什么会发生这种情况,但是将文件模式从“ w”更改为“ wb”可以解决此问题。有关更多详细信息,请参见我对“ 如何删除^ M ”的回答。



2

请注意,如果使用DictWriter,则open函数将有新行,而writerow函数将有新行。您可以在open函数中使用newline =''来删除多余的换行符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.