file.readlines() 只会拆分为 \n、\r 或 \r\n,具体取决于操作系统以及是否启用了通用换行支持。
U+0085 NEXT LINE (NEL) 在该上下文中未被识别为换行符,您无需执行任何特殊操作即可让file.readlines() 忽略它。
引用open() function documentation:
Python 通常在构建时支持通用换行符;提供'U' 将文件作为文本文件打开,但行可能被以下任何一种终止:Unix 行尾约定'\n'、Macintosh 约定'\r' 或Windows 约定'\r\n'。所有这些外部表示都被 Python 程序视为'\n'。如果 Python 是在没有通用换行符的情况下构建的,则支持 'U' 的模式与普通文本模式相同。请注意,如此打开的文件对象还有一个名为 newlines 的属性,其值为 None(如果尚未看到换行符)、'\n'、'\r'、'\r\n',或包含所有看到的换行符类型的元组。
还有universal newlines glossary entry:
一种解释文本流的方式,其中以下所有内容都被识别为结束行:Unix 行尾约定'\n'、Windows 约定'\r\n' 和旧的Macintosh 约定'\r'。有关其他用途,请参阅 PEP 278 和 PEP 3116 以及 str.splitlines()。
不幸的是,codecs.open() 违反了这条规则; documentation 含糊地暗示了被询问的特定编解码器:
行尾是使用编解码器的解码器方法实现的,如果 keepends 为真,则包含在列表条目中。
不要使用codecs.open(),而是使用io.open()以正确的编码打开文件,然后逐行处理:
with io.open(filename, encoding=correct_encoding) as f:
lines = f.open()
io 是全新的 I/O 基础架构,在 Python 3 中完全取代了 Python 2 系统。它只处理 \n、\r 和 \r\n:
>>> open('/tmp/test.txt', 'wb').write(u'Line 1 \x85 Line 1.1\r\nLine 2\r\nLine 3\r\n'.encode('utf8'))
>>> import codecs
>>> codecs.open('/tmp/test.txt', encoding='utf8').readlines()
[u'Line 1 \x85', u' Line 1.1\r\n', u'Line 2\r\n', u'Line 3\r\n']
>>> import io
>>> io.open('/tmp/test.txt', encoding='utf8').readlines()
[u'Line 1 \x85 Line 1.1\n', u'Line 2\n', u'Line 3\n']
codecs.open() 的结果是由于使用了str.splitlines() 的代码,其中has a documentation bug;拆分 unicode 字符串时,它将拆分 Unicode 标准认为是换行符的任何内容(即quite a complex issue)。这种方法的文档没有解释这一点;它声称只根据通用换行规则进行拆分。