【问题标题】:Python Write Replaces "\n" With "\r\n" in WindowsPython 写入在 Windows 中将“\n”替换为“\r\n”
【发布时间】:2017-11-20 03:24:35
【问题描述】:

查看我的问题here后,我发现这是由一个更简单的问题引起的。

当我将"\n" 写入文件时,我希望从文件中读取"\n"。在 Windows 中并非总是如此。

In [1]: with open("out", "w") as file:
   ...:     file.write("\n")
   ...:

In [2]: with open("out", "r") as file:
   ...:     s = file.read()
   ...:

In [3]: s  # I expect "\n" and I get it
Out[3]: '\n'

In [4]: with open("out", "rb") as file:
   ...:     b = file.read()
   ...:

In [5]: b  # I expect b"\n"... Uh-oh
Out[5]: b'\r\n'

In [6]: with open("out", "wb") as file:
   ...:     file.write(b"\n")
   ...:

In [7]: with open("out", "r") as file:
   ...:     s = file.read()
   ...:

In [8]: s  # I expect "\n" and I get it
Out[8]: '\n'

In [9]: with open("out", "rb") as file:
   ...:     b = file.read()
   ...:

In [10]: b  # I expect b"\n" and I get it
Out[10]: b'\n'

以更有条理的方式:

| Method of Writing | Method of Reading | "\n" Turns Into |
|-------------------|-------------------|-----------------|
| "w"               | "r"               | "\n"            |
| "w"               | "rb"              | b"\r\n"         |
| "wb"              | "r"               | "\n"            |
| "wb"              | "rb"              | b"\n"           |

当我在我的 Linux 虚拟机上尝试这个时,它总是返回 \n。如何在 Windows 中执行此操作?

编辑: 这对于 pandas 库尤其成问题,它似乎将DataFrames 写入csv"w" 并读取csvs 与"rb"。有关此示例,请参阅顶部链接的问题。

【问题讨论】:

  • 在文本模式下,Python 将所有行尾替换为系统默认值。使用二进制模式并自己编码字符串以使用自定义行尾。
  • 或者,在打开文件时指定行尾。这可能是一种更清洁的方法。

标签: windows python-3.x read-write


【解决方案1】:

由于您使用的是 Python 3,因此您很幸运。当您打开文件进行写入时,只需指定newline='\n' 以确保它写入'\n' 而不是系统默认值,即Windows 上的\r\n。来自docs

将输出写入流时,如果newlineNone,则写入的任何'\n' 字符都将转换为系统默认行分隔符os.linesep。如果换行符是'''\n',则不进行翻译。如果newline 是任何其他合法值,则写入的任何'\n' 字符都将转换为给定字符串。

您认为“有时”会看到两个字符的输出的原因是,当您以二进制模式打开文件时,根本没有进行任何转换。为方便起见,尽可能以 ASCII 显示字节数组。在解码之前不要将它们视为真正的字符串。您显示的二进制输出是所有示例中文件的真实内容。

当您以默认文本模式打开文件进行读取时,newline 参数的工作方式与写入的方式类似。默认情况下,文件中的所有\r\n 将在字符解码后仅转换为\n。当您的代码在操作系统之间传输但文件不传输时,这非常好,因为您可以使用仅依赖于\n 的完全相同的代码。如果您的文件也传输,您应该坚持使用相对便携的newline='\n' 至少输出。

【讨论】:

    【解决方案2】:

    来自the documentation

    newline 控制通用换行模式的工作方式(它仅适用于文本模式)。它可以是None'''\n''\r''\r\n'。它的工作原理如下:

    [...]

    • 将输出写入流时,如果 newlineNone,则写入的任何'\n' 字符都将转换为系统默认行分隔符os.linesep。如果 newline'''\n',则不进行翻译。如果 newline 是任何其他合法值,则写入的任何 '\n' 字符都将转换为给定字符串。
    open(..., 'w', newline='')
    

    【讨论】:

      【解决方案3】:

      文件的编码通常取决于系统。正如上面的答案所提到的,如果它对我们有用,我们可以将换行选项硬编码为 '\n'。但是,当您从云中获取文件或数据时,此方法将不起作用,因为它们通常具有受限访问权限并被解析为轻量级可移植文件格式。因此,删除默认二进制或任何其他编码的最佳方法是对任何编码数据使用带有file.read() 输出的decode() 方法。 例如,在你的情况下

      In [1]: with open("out", "w") as file:
         ...:     file.write("\n")
      
      In [q]: with open("out", "file permission") as file:
         ...:     s = file.read().decode()
      
      #--------------------------- OR --------------------------c
      
      In [q`]: with open(..., newline='delimiter of your choice') as file:
         ...:     s = file.read()  
      
      
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-03-22
        • 2011-06-16
        • 2015-07-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-23
        相关资源
        最近更新 更多