Python中的readline()错误

1 投票
3 回答
1681 浏览
提问于 2025-04-17 20:45

我在使用readline()这个方法时遇到了问题,有时候它会返回两行而不是一行,我不知道为什么。有人能帮我吗?

这是我用记事本打开的文本文件的一部分:

at+gpsinit=2
OK

+GPSEVINIT: 1
at+gpsnmea=3
OK
at+gpsstart=0
OK

用Notepad++打开的效果:

at+gpsinit=2CR
CR LF
OKCR LF
CR LF
+GPSEVINIT: 1CR LF
at+gpsnmea=3CR
CR LF
OKCR LF
at+gpsstart=0CR
CR LF
OKCR LF

这是我在Python命令行中看到的结果:

16 : at+gpsinit=2

17 : 

18 : OK

19 : 

20 : +GPSEVINIT: 1

21 : at+gpsnmea=3

这是我的代码:

# Open a file
file = open("testtxt.txt", 'r')
line = 0

for current_line in file:
    line += 1    
    print(str(line)+" : "+current_line)

# Close opend file
file.close()

3 个回答

1

readline()这个功能里肯定没有bug,因为很多人都在用它,而且用得很频繁。除非你用的是一种非常奇怪的、不是标准Python的版本,否则你用的应该也是个不错的版本。

你提供的信息还不足以让人确定你遇到问题的原因,不过我可以给你一些分析的方法,帮助你找出问题所在。

你应该仔细看看你的每一行里面有什么,特别是哪些字节是用来结束这一行的(比如'\n'或者'\r\n'等等),尤其要关注一下这一行at+gpsinit=2及其结尾部分。

如果你在Unix系统上,可以用od(或者xxd)来查看。使用-c选项可以打印出字符。再加上-t x1 -t c选项,就能同时看到每个字节的十六进制输出和字符输出。

2

你遇到的问题很可能是因为行结束符的问题。

  • 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

正如你所看到的,单词 hello68 65 6c 6c 6f)后面跟着不同的字节 0d 0a0a0d。当你在 MS-记事本中编辑文件时,你很可能会插入 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" 的例子只有一行的原因。

如果你需要处理来自不同来源的文件,可以考虑在 open 函数中使用 U 标志来激活 "通用换行符" 支持。详细信息可以查看 open 的文档。

这里有一个例子。请注意,唯一改变的是 openU 参数:

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。不过,我相信这不是默认设置是有原因的! :)

0

好的,我解决了我的问题,看来是Np给了我错误的文本文件。无论如何,我使用了这个命令:

file = open("testtxt.txt", 'r', newline="\r\n")

结果得到了正确的内容。

撰写回答