在Mac和Windows上处理Python中的\r\n和\n换行符

42

我有一个Python脚本,在Windows机器上运行和在Mac上运行时会产生不同的输出。深入挖掘后,我发现这是因为当Python读取来自Mac(从文件)的换行符时,它读取了\r\n,而在Windows中,\r消失了。

因此,如果我将脚本中的每个\n更改为\r\n,它在Mac上可以正常工作。但如果我这样做,它就不能在Windows PC上运行。

有没有简单的方法解决这个问题?


1
你在从文件中读取时遇到了这个错误?你使用的是哪个版本的Python?你是从哪里获取的?Python通常内置了通用换行符支持。 - Falmarri
@Falmarri Python 3... 我很确定我是从官方Python网站上获取的。 - wrongusername
4
这里是又一次Windows与Linux之间的不一致性 - 在Windows上,Python的glob.glob函数总是按字母顺序排序返回文件名列表。而在Linux上,文件名列表会随机返回。 - PaulMcG
2
glob.glob 并没有声明以任何特定顺序返回结果,因此没有理由期望它们按任何特定顺序排列。 - Mark
5个回答

46

不同平台使用不同的代码表示“换行”。Windows使用\r\n,Unix使用\n,旧版mac使用\r,是的,有些系统使用\n\r。

当你在Python 3中以文本模式打开文件时,它会将所有换行符转换为'\n'并完成。

infile = open("filename", 'r')

文本模式是默认的,所以如果你什么也不说,就是文本模式。但明确说明总是更好的选择:

infile = open("filename", 'rt')

如果你不想进行行结束符的翻译,请以二进制模式打开文件:

infile = open("filename", 'rb')

在Python 2中,情况有所不同。只有在Windows上默认情况下才会发生这种转换。 如果你想在其他平台上也进行转换,可以添加通用换行符标志:

infile = open("filename", 'rU')

但是您说您正在使用Python 3,而在文本模式下,在所有平台上都会发生这种情况,因此添加U标志不应该有任何区别。


非常感谢,我有一个想法就是这样,花了很长时间才确认,但是我的代码在Python 2.7上运行正常,在Python 3.2上由于这个差异而出现了故障。我需要用“rb”来解决它...谢谢,解释得非常透彻。 - sinekonata
在文本模式下,os.linesep 在所有平台(不仅仅是 Windows)上都被替换为 \n。如果 os.linesep == '\n',则在 Python 2 中与无转换相同。 - jfs
@J.F.Sebastian:实际上这意味着它只会在Windows上发生(以及Mac OS 9,但自Python 2.4以来不再支持)。而在Python 3中,所有换行符组合都将在所有平台上转换为 '\n' - Lennart Regebro
如果您使用codecs.open(),那么如何处理这个问题? - Intelligent-Infrastructure
Codecs.open() 函数还可以接受文件模式标志。 - Lennart Regebro

25

'U'模式:

Python 2:

我猜这可能取决于你正在读什么,但是内置的 open() 函数需要一个“mode”参数,如果你将模式设置为 'U',Python 2 将以透明的跨平台方式处理换行符。 这需要使用支持通用换行符的 Python 构建进行操作,但可以试试!

https://docs.python.org/2/library/functions.html#open

Python 3:

在Python 3中,默认行为是使用'U'模式,正如文档所解释的那样:

还有一个额外的模式字符'U',它不再起作用,并被视为弃用。它之前启用了universal newlines以在文本模式下成为默认行为。有关详细信息,请参阅newline参数的文档。

https://docs.python.org/3/library/functions.html#open


1
这也是默认设置(据我所知) - Falmarri
嗯,听起来在Python 3中这不是默认设置。那似乎很奇怪。 - Falmarri
7
@Falmarri:在Python 3中,它是默认设置,并且实际上,在Python 3中,U标志已被弃用。 - Lennart Regebro
1
@wrongusername:不,这在Python 2.6下也可以正常工作。启动python解释器时你会看到Python的版本。 - Lennart Regebro
1
@MikeB 该功能本身并未被弃用,它是默认的。您无需执行任何操作即可启用它。当您以文本模式打开文件时,它会以通用换行符模式打开。被弃用的是特别设置 mode="U"。如果您想要禁用通用换行符,则可以传递 newline="\n" 或其他内容。请参见此问题 - user3064538
显示剩余7条评论

8
在Python 3中,Open()方法有一个newline参数:

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

当从流中读取输入时,如果newline为None,则启用通用换行模式。输入中的行可以以'\n'、'\r'或'\r\n'结尾,这些在返回给调用者之前将被转换为'\n'。如果它是'',则启用通用换行模式,但行末不会被翻译并原样返回给调用者。如果它有任何其他合法值,则输入行仅由给定字符串终止,并且行结束未被翻译并原样返回给调用者。

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

U模式说明符的旧方式已被弃用,建议使用这种新方式。

7

1
在Windows上,如果我使用(\r或\n)写一个文件,Python会将它们都解释为换行符,两种情况下都能正常工作。而使用"\r\n"时,它被解释为双重换行符。(Python 3 on Windows)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接