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可能会发生此行为。
#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.reader
或csv.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
评论
Python 2 CSV编写器的可能重复项在Windows上产生了错误的行终止符