我在努力解释为什么python将回车符解码为换行符。
在这里,我以一个示例的文本文件为例,其中一行包含一个回车符(\ r)。 如果我将其作为指定编码的文本文件打开,则找不到以二进制模式打开文件并使用相同的编码对其进行解码的字符串。
实际上,当我以文本模式打开文件时,CR字符被换行符(\ n)代替。
为什么?
with open("text.txt", encoding="utf-8", mode="r") as f:
txt = f.read()
txt
>>>'4312;"blabla";";\n";"blabla2"\n'
with open("text.txt", mode="rb") as f:
txt2 = f.read()
txt2.decode("utf-8")
>>>'4312;"blabla";";\r";"blabla2"\n'
答案 0 :(得分:3)
这与编码无关。
以“ r”(文本)模式打开文件时,除非您指定其他内容,否则将应用通用换行符支持。如下所示:
从流中读取输入时,如果换行为None,则为通用 换行模式已启用。输入中的行可以以'\ n','\ r'或 '\ r \ n',并且在返回之前将其转换为'\ n' 呼叫者。
在io.TextIOWrapper
类下的https://docs.python.org/3/library/io.html。
当您以“ rb”(二进制)模式打开文件时,您将确切地获得文件中的内容。
文件中似乎有\r
,当您以文本模式阅读文件时,您将其标准化为\n
。但是在二进制模式下,(当然)它没有被规范化,因此您会得到文件中实际存在的不一致的EOL。
答案 1 :(得分:2)
这是因为默认情况下启用的open
函数的通用换行模式会自动将'\r'
和'\r\n'
标准化为'\n'
。如果您希望保留原始的行尾,则可以使用newline=''
参数:
with open("text.txt", encoding="utf-8", mode="r", newline='') as f:
摘录自documentation:
newline
控制通用换行符的工作方式(仅适用于文本 模式)。它可以是None,''
,'\n'
,'\r'
和'\r\n'
。它作为 如下:
- 在输入时,如果
newline
为None
,则启用通用换行模式。输入中的行可以以'\n'
,'\r'
或'\r\n'
结尾,它们是 在返回给呼叫者之前将其翻译成'\n'
。如果是''
, 通用换行模式已启用,但行尾返回到 呼叫者未翻译。如果它具有其他任何法律价值, 输入行仅由给定的字符串终止,并且该行 结尾将不翻译地返回给调用方。- 在输出中,如果
newline
为None
,则任何写入的'\n'
字符都将转换为系统默认的行分隔符os.linesep
。如果 换行符为''
,不进行任何翻译。如果newline
是 其他合法值,则将任何写入的'\n'
字符翻译为 给定的字符串。
答案 2 :(得分:2)
open默认参数的完整列表为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
newline=None
参数位于您注意到的行为之后。如果未指定此参数(也称为anewline = None),则会导致激活“通用换行模式”。如文档here中所述,这意味着\r\n
将自动翻译为\n
:
在输入时,如果换行符为“无”,则启用通用换行符模式。 输入中的行可以以'\ n','\ r'或'\ r \ n'结尾,这些是 在返回给调用者之前先翻译为“ \ n”。
当您使用mode=rb
打开文件时,数据将作为字节加载并且不会被解码,因此不会完成\r
到\n
的自动转换。
以二进制模式打开的文件(在mode参数中包括“ b”) 将内容作为字节对象返回而无需任何解码
有关PEP 278 -- Universal Newline Support中通用换行符支持的更多信息。