【问题标题】:Wrong readline() in PythonPython 中的 readline() 错误
【发布时间】:2014-03-04 10:17:48
【问题描述】:

我的 readline() 方法有问题,它有时会返回 2 行而不是 1 行,我不知道为什么。有人可以帮我吗?

这是我阅读的文本文件的一部分(使用记事本):

at+gpsinit=2
OK

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

还有记事本++:

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 shell 中得到的:

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()

【问题讨论】:

  • 嗯,我觉得很好。
  • 请注意,“at+gpsinit=2”和“OK”之间没有换行,所以我不明白为什么会有17个“空白”行。
  • 空行也是行。
  • 你是说'at+gpsinit=2'和'OK'之间没有空行吗?
  • 是的,我更新了我的帖子,我意识到我写错了,第 19 行是正确的,但第 17 行不是。

标签: python file text newline


【解决方案1】:

您遇到的问题很可能是由于行尾标记的问题。

  • 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-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。但是,我确信它不是默认设置是有充分理由的! :)

【讨论】:

    【解决方案2】:

    readline() 例程中肯定没有错误;太多人经常使用它,除非你有一个非常奇怪的不是标准 Python 的实现,否则你也会使用一个不错的版本。

    您提供的信息不足以确定您的问题的原因是什么,但我建议您使用一些分析方法来找出您正在处理的问题。

    您应该仔细查看行中的内容,哪些字节会终止您的行('\n''\r\n' 或其他),并特别仔细查看行 at+gpsinit=2 及其结尾。

    在 Unix 系统上,您可以为此使用 od(或 xxd)。使用选项-c 会打印字符。使用-t x1 -t c 也可以获得每个字节的十六进制输出。

    【讨论】:

    • 是的,谢谢,我得出了同样的结论,我用记事本++而不是记事本读取文件,实际上在第16行的末尾和第 17 行有“CR LF”。
    【解决方案3】:

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

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

    它给了我很好的台词。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 2016-01-22
      相关资源
      最近更新 更多