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

apa*_*apa 202 python windows csv newline

在运行Windows XP专业版的Python 2.7中:

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()
Run Code Online (Sandbox Code Playgroud)

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

test.csv

hi,dude\r\r\nhi2,dude2\r\r\n
Run Code Online (Sandbox Code Playgroud)

而不是预期的:

hi,dude\r\nhi2,dude2\r\n
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*hin 270

在Windows上,始终以二进制模式("rb"或"wb")打开文件,然后再将它们传递给csv.reader或csv.writer.

虽然该文件是文本文件,但CSV被所涉及的库视为二进制格式,"\ r \n"分隔记录.如果该分隔符是以文本模式编写的,则Python运行时将"\n"替换为"\ r \n",因此将在文件中观察到的"\ r \n \n \n"替换为"\ r \n \n".

请参阅此前一个答案.


这个答案发布于2010年,并没有解决Python3中的问题.

如@ YiboYang的回答所述,Python3中的一个可能的修复是打开文件,newline=''参数设置为空字符串:

with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
Run Code Online (Sandbox Code Playgroud)

  • 在Python 3中,我能够通过对文件对象使用以下选项来修复它:`open(...,"w",newline ="\n",encoding ="utf-8")`.`newline`也可以是空字符串,结果相同.`"wb"`在Python 3中不起作用,字符串和缓冲区接口不兼容. (64认同)
  • 也是"ab"以二进制格式附加. (9认同)
  • 有多少开发人员踩着火红的大便是CSV? (8认同)
  • 这对于ASCII很好,但会像UTF-8一样杀死编码.Jason的解决方案适用于我. (3认同)
  • 真遗憾,这样的基本,通用和简单的API无法按要求工作 (2认同)

Jas*_*mbs 231

虽然@ john-machin给出了一个很好的答案,但并不总是最好的方法.例如,除非您将所有输入编码为CSV编写器,否则它不适用于Python 3.此外,如果脚本要使用sys.stdout作为流,则不会解决此问题.

我建议在创建编写器时设置'lineterminator'属性:

import csv
import sys

doc = csv.writer(sys.stdout, lineterminator='\n')
doc.writerow('abc')
doc.writerow(range(3))
Run Code Online (Sandbox Code Playgroud)

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

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

  • 在我看来,这是最好的答案.至于在Unix中存在问题,如何调用sys.platform并动态处理它? (6认同)
  • 在我看来也是最佳答案,而lineterminator ='\n'的效果非常好. (4认同)
  • 当心:使用这意味着`\r` 不再转义!看起来这是 `csvwriter` 中的错误,但就目前而言,输出不符合标准的 CSV 意味着 * 不是 * 可行的方法。 (3认同)
  • 如果您不“对 CSV 编写器的所有输入进行编码”,您能否举例说明出现的问题? (2认同)
  • 顺便说一句,我想知道和@Stephen一样,显然_“除非你编码,否则它在Python 3上不起作用”_指的是另一个答案的2010年版本,它推荐`open(..., 'wb' )` 没有说它仅适用于 Python 2。我[不相信实际上可以让 csvwriter 在 Python 3 中使用“wb”文件对象](/sf/ask/375082571/)。 (2认同)

Yib*_*ang 51

在Python 3中(我没有在Python 2中尝试过这个),你也可以这样做

with open('output.csv','w',newline='') as f:
    writer=csv.writer(f)
    writer.writerow(mystuff)
    ...
Run Code Online (Sandbox Code Playgroud)

根据文件.

在doc的脚注中有更多相关内容:

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

  • 大.我在python 3.5中证实了这一点 (3认同)
  • 不幸的是,不适用于Python 2 (2认同)
  • @Yibo-Yang,你救了我很多时间. (2认同)
  • @MarcStober,因为对于大多数打开的文件,您希望将换行符转换为平台默认值。仅当您需要完全控制行终止符的处理方式时,您才需要设置`newline=''`。就像编写符合 RFC 的 CSV 数据一样。请注意,**不是“CSV”模块在此处打开文件**。 (2认同)

Wes*_* Na 9

您可以在 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'])
Run Code Online (Sandbox Code Playgroud)

  • 对于 Python 3.5.2,这是唯一对我有用的东西(好吧,我只使用了 `lineterminator='\n'`);CSV 模块似乎是“\r\n”的起源。“open”的任何参数都没有任何效果。 (4认同)

归档时间:

查看次数:

138358 次

最近记录:

6 年,5 月 前