您遇到的问题很可能是由于行尾标记的问题。
- Windows/Dos 通常使用
CRLF(或\r\n,或0d0a,以字节为单位)。
- Unix 通常使用
LF(或\n,或0a,以字节为单位)
- MacOS 通常使用
CR(或\r,或0d,以字节为单位)
以下是 ASCII 编码文件的一些示例:
$ hexdump -C test_dos.txt
00000000 68 65 6c 6c 6f 0d 0a 77 6f 72 6c 64 0d 0a |hello..world..|
0000000e
$ hexdump -C test_nix.txt
00000000 68 65 6c 6c 6f 0a 77 6f 72 6c 64 0a |hello.world.|
0000000c
$ hexdump -C test_mac.txt
00000000 68 65 6c 6c 6f 0d 77 6f 72 6c 64 0d |hello.world.|
0000000c
你可以看到,hello(68 65 6c 6c 6f)这个词后面分别跟着不同的字节0d 0a、0a或0d。当您在 MS-Notepad 中编辑文件时,您很可能会插入 CRLF。由于LF 在软件开发中最常见,Notepad++ 最有可能添加这些。
现在,对于您的代码:鉴于上面的三个文件,与您的代码类似的代码会产生以下结果:
代码:
files = ('test_dos.txt', 'test_nix.txt', 'test_mac.txt')
for fname in files:
print("Reading {}".format(fname))
with open(fname) as fptr:
for line in fptr:
print("--> {!r}".format(line))
print(80*"-")
输出:
Reading test_dos.txt
--> 'hello\r\n'
--> 'world\r\n'
--------------------------------------------------------------------------------
Reading test_nix.txt
--> 'hello\n'
--> 'world\n'
--------------------------------------------------------------------------------
Reading test_mac.txt
--> 'hello\rworld\r'
--------------------------------------------------------------------------------
您可以清楚地看到,Python 在 \n 字符上进行拆分,但不会将其从输出中删除。这就是“mac”示例只有一行的原因。
如果您必须处理来自异构来源的文件,请考虑使用U 标志激活“通用换行符”支持open。
这是一个例子。请注意,唯一改变的是将U 参数更改为open:
files = ('test_dos.txt', 'test_nix.txt', 'test_mac.txt')
for fname in files:
print("Reading {}".format(fname))
with open(fname, 'U') as fptr:
for line in fptr:
print("--> {!r}".format(line))
print(80*"-")
输出:
Reading test_dos.txt
--> 'hello\n'
--> 'world\n'
--------------------------------------------------------------------------------
Reading test_nix.txt
--> 'hello\n'
--> 'world\n'
--------------------------------------------------------------------------------
Reading test_mac.txt
--> 'hello\n'
--> 'world\n'
--------------------------------------------------------------------------------
如您所见,并非所有文件的行为都相同。这可能会提示您在阅读文本文件的任何地方都输入U。但是,我确信它不是默认设置是有充分理由的! :)