【问题标题】:CSV in Python adding an extra carriage return, on WindowsPython中的CSV在Windows上添加了一个额外的回车符
【发布时间】:2011-03-12 14:46:41
【问题描述】:
import csv

with open('test.csv', 'w') as outfile:
    writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
    writer.writerow(['hi', 'dude'])
    writer.writerow(['hi2', 'dude2'])

上面的代码生成了一个文件test.csv,每行都有一个额外的\r,如下所示:

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

而不是预期的

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

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

【问题讨论】:

标签: python windows csv newline


【解决方案1】:

Python 3:

官方csv documentation推荐open将所有平台上带有newline=''的文件转为disable universal newlines translation

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

CSV 编写器以lineterminator of the dialect 结束每一行,这是所有平台上默认excel 方言的'\r\n',因为这是RFC 4180 推荐的。


Python 2:

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

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

this previous answer

【讨论】:

    【解决方案2】:

    虽然@john-machin 给出了一个很好的答案,但这并不总是最好的方法。例如,它不适用于 Python 3,除非您将所有输入编码到 CSV 编写器。此外,如果脚本想要使用 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 编写器”会出现的问题?
    • 注意:使用这意味着\r 不再被转义!看起来这是 csvwriter 中的错误,但就目前而言,输出不符合标准的 CSV 意味着这不是要走的路。
    • 这为我解决了 ^M 问题,而接受的答案的 2 条建议不起作用。
    • 顺便说一句,我想知道和@Stephen 一样,显然 “除非你编码,否则它在 Python 3 上不起作用” 指的是另一个答案的 2010 版本,它推荐了open(..., 'wb'),但没有说它仅适用于 Python 2。我don't believe it's actually possble to have the csvwriter work with a 'wb' file object in Python 3.
    • 最后我认为 “它可能会产生不受欢迎的换行符(在 Unix 操作系统上省略 LF 字符)。” 应该意味着使用 lineterminator='\n' hack, excel 方言将在 Unix 上使用 \n,而不是像 it's supposed to 这样的 \r\n
    【解决方案3】:

    在 Python 3 中(我没有在 Python 2 中尝试过),你也可以简单地做

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

    根据documentation

    更多信息请参见文档的footnote

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

    【讨论】:

    • 为什么这不是默认行为?
    • @MarcStober 因为对于大多数打开的文件,您希望将换行符转换为平台默认值。当您需要完全控制线路终结符的处理方式时,您只需要设置newline=''。就像编写符合 RFC 的 CSV 数据一样。请注意,在此处打开文件的不是 CSV 模块
    【解决方案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 的起源。 open 的任何参数都没有任何效果。
    【解决方案5】:

    你必须添加属性 newline="\n" 来打开这样的函数:

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

    【讨论】:

    • 不,您需要发送至 Sennewline='' 并让 CSV 模块完全控制行终止符的写入方式。 CSV 格式使用\r\n 终止符不管操作系统默认的单独终止符
    • newline=''newline='\n' 在打开文件以写入 according to the docs 时具有完全相同的效果,所以我认为这个答案不会添加任何内容
    【解决方案6】:

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

    【讨论】:

    • 这与 DictWriter 无关。 DictWriter 是围绕CSV.writer() 的包装类,它不添加换行符。没有“额外的换行符”。
    猜你喜欢
    • 2016-09-05
    • 2017-11-21
    • 1970-01-01
    • 2021-10-28
    • 2019-04-11
    • 2020-04-07
    相关资源
    最近更新 更多