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可能会发生此行为。


评论

Python 2 CSV编写器的可能重复项在Windows上产生了错误的行终止符

#1 楼

Python 3:
官方的csv文档建议在所有平台上使用open对该文件进行newline=''编码,以禁用通用换行符翻译:
 with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...
 

CSV编写器以方言的lineterminator结束每一行,在所有平台上默认的\r\n方言都是excel

Python 2:
在Windows上,请始终打开文件以二进制模式("rb""wb")传递给csv.readercsv.writer之前。
尽管该文件是文本文件,但所涉及的库将CSV视为二进制格式,其中\r\n分隔记录。如果该分隔符以文本模式编写,则Python运行时将\n替换为\r\n,因此在文件中观察到了\r\r\n
请参见前面的答案。

#2 楼

尽管@ 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视为二进制格式。我提供此答案作为您考虑的替代方法。

评论


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

–斯蒂芬
17年7月15日在8:02

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

– flow2k
19 Mar 8 '19 at 21:41

这为我解决了^ M问题,而接受的答案的2条建议无效。

–user985366
1月29日10:10

注意:@ flow2k报告了bugs.python.org/issue36246,该问题已得到修复(“按文档所述工作”)。也许使用csvwriter编写单独的CR字符并不常见,但是这种lineterminator ='\ n'解决方案(就像Python中的通用换行符一样)闻起来很糟糕。我更喜欢使用newline =''禁用通用换行符(或针对stdout的此hack)。如果要摆脱所有CR,而不仅仅是重复的CR,就像@ user985366可能要做的那样,还可以将方言更改为“ unix”。

– Nickolay
10月17日12:47



顺便说一句,我想知道与@Stephen相同,并且显然“除非您编码,否则它在Python 3上不起作用”是指其他答案的2010年版本,它建议使用open(...,'wb')而不用说它仅适用于Python 2。我不认为让csvwriter与Python 3中的'wb'文件对象一起工作实际上是不可能的。

– Nickolay
10月17日12:48

#3 楼

在Python 3中(我还没有在Python 2中尝试过此操作),您也可以根据文档简单地

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




更多在文档的脚注中对此进行以下说明:


如果未指定newline ='',则在使用\ r的平台上,嵌入行中引用的字段
中的换行符将无法正确解释。 \ n
附加笔迹将被添加。指定csv模块应该始终
安全,因为csv模块会自己进行
(通用)换行处理。


评论


为什么这不是默认行为?

– Marc Stober
18年5月23日在12:43

@MarcStober,因为对于大多数打开的文件,您希望换行符转换为平台默认值。您只需要在需要完全控制行终止符的处理方式时才设置newline =''。就像在编写符合RFC的CSV数据时一样。请注意,不是CSV模块在此处打开文件。

–马丁·彼得斯(Martijn Pieters)♦
10月29日21:06

#4 楼

您可以在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'])


评论


在Python 3.5.2中,这是唯一对我有用的东西(嗯,我只使用了lineterminator ='\ n')。 CSV模块似乎是\ r \ n的起源。没有任何打开参数集有效。

–汤米(Tommy)
19年1月24日,19:30



#5 楼

您必须添加属性newline =“ \ n”才能打开如下功能:

with open('file.csv','w',newline="\n") as out:
    csv_out = csv.writer(out, delimiter =';')


评论


不,您需要Sennewline =''并为CSV模块完全控制行终止符的编写方式。 CSV格式使用\ r \ n终止符,而与操作系统默认的单独终止符无关。

–马丁·彼得斯(Martijn Pieters)♦
10月29日21:08

#6 楼

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

评论


这与DictWriter无关。 DictWriter是CSV.writer()的包装类,它不添加换行符。没有“多余的换行符”。

–马丁·彼得斯(Martijn Pieters)♦
10月29日21:10