【问题标题】:Python file.tell() giving strange numbers?Python file.tell() 给出奇怪的数字?
【发布时间】:2013-04-10 19:41:51
【问题描述】:

我在 Windows 64 位上使用 Python 3.3.0。

我有一个如下所示的文本文件:(mediafire 的下载链接见底部)

hello

-data1:blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah


-data2:blah blah blah blah blah blah blah blah blah blah blah
-data3: Empty

-data4: Empty

我正在尝试浏览文件,因此我使用.tell() 来确定我的位置。但是,当阅读如下所示的文件行时,我得到了一个非常奇怪的结果:

f=open("test.txt")
while True:
    a = f.readline()
    print("{}    {}".format(repr(a),f.tell()))
    if a == "":
        break

结果:

'hello\n'    7
'\n'    9
'-data1:blah blah blah blah blah blah blah blah blah blah blah blah blah blah bl
ah blah\n'    18446744073709551714
'\n'    99
'\n'    101
'-data2:blah blah blah blah blah blah blah blah blah blah blah\n'    164
'-data3: Empty\n'    179
'\n'    181
'-data4: Empty'    194
''    194

第 3 行的 18446744073709551714 是怎么回事?虽然它看起来像是一个不可能的值,但f.seek(18446744073709551714) 是一个可以接受的值,显然它确实让我走到了第三行的末尾。不过,我似乎无法弄清楚为什么。

编辑: 以二进制模式打开tell() 没有问题:

f=open("test.txt","rb")
while True:
    a = f.readline()
    print("{}    {}".format(repr(a),f.tell()))
    if a == b"":
        break

结果:

b'hello\r\n'    7
b'\r\n'    9
b'-data1:blah blah blah blah blah blah blah blah blah blah blah blah blah blah b
lah blah\r\n'    97
b'\r\n'    99
b'\r\n'    101
b'-data2:blah blah blah blah blah blah blah blah blah blah blah\r\n'    164
b'-data3: Empty\r\n'    179
b'\r\n'    181
b'-data4: Empty'    194
b''    194

test.txt 文本文件可在此处下载,只有 194 字节:http://www.mediafire.com/?1wm4lujb2j48y23

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    这是由 UNIX 样式的行尾引起的记录行为:

    file.tell()

    返回文件的当前位置,如stdioftell()

    注意:在 Windows 上,tell() 在读取具有 Unix 样式行尾的文件时可能返​​回非法值(在 fgets() 之后)。使用二进制模式 ('rb') 来规避这个问题。


    以上文档摘自python2.7.4文档。 python3 的文档发生了一些变化,因为现在有一个处理 I/O 的类的层次结构,我找不到这些信息。您的测试表明行为并没有改变。此外,python3.3 的源代码在tell 调用的函数之前有一个XXX Windows support below is likely incomplete 注释。


    在python bug tracker中有一个issue与此相关,Catalin Iacob的最后评论是:

    我试图重现这个,在我的磁盘上选择了一个文件,确实我得到了一个 负数,但该文件具有 Unix 行结尾。这是 记录在http://docs.python.org/2/library/stdtypes.html#file.tell 所以可能没有什么可做的。

    至于阿明在msg180145中的报告,虽然不直观, 这符合 ftell 在 Windows 上的行为,如备注中所述 部分 http://msdn.microsoft.com/en-us/library/0ys3hc0b%28v=vs.100%29.aspx。 文件对象上的 tell() 方法被明确记录为匹配 ftell 行为:“返回文件的当前位置,如 stdio 的 ftell()"。所以即使它根本不直观,它也可能是 最好保持原样。 tell() 返回直观的非零 在 Python3 和 Python 2.7 上使用“a”打开时的位置 io.open 所以它在未来是固定的。

    所以这似乎是一个“不会修复”的错误。 可能有人应该打开一个问题(评论了这个问题),因为这个事实在 python3 文档中根本没有提到。


    根据Antoine Pitrou,python3 根本不使用ftell(),因此这似乎是一个不同的错误。此外,该错误在 python3.2.3 中不可重现,并且可能是在修复此 issue 时引入的(至少,这是我在 3.2.3 和 3.3 之间找到的对 tell() 实现的唯一更改)


    上次编辑:根据io 模块文档,tell 方法确实返回自文件开头以来的字节数。返回值是一个“不透明数字”,这意味着您可以使用它的唯一方法是将其传递给seek 以返回该位置。其他操作没有意义。事实上,在 python3.2.3 之前返回的值是您所期望的,这只是一个实现细节。

    请注意,文档的this 部分中的信息完全是错误,希望将来会更正。

    【讨论】:

    • 呃,等等,文本文件只是使用记事本创建的。并使用显示行尾的notepad2,我看到CR + LF,这是windows行尾吗? Unix 行尾只有 LF 对吗?在修改了我的测试文件之后,显然,更长的行更有可能出现这个问题。
    • @Eric 您是否尝试从 python 以二进制模式打开文件并查看内容?另外,您能否在某处发布文件内容/上传文件以便我们也可以进行测试?我的 AFAIK 是唯一合理的解释,我坚信 python 的文件是正确的,所以我仍然认为问题仅仅是对 ftell() 的底层调用返回垃圾。
    • 我在二进制模式下用同样的东西编辑了原始问题,并将文本文件上传到了 mediafire。
    • @Eric 那么这是一个新错误。请参阅错误跟踪器的更新答案和链接问题。
    • @Eric 好的。根据 python 的开发人员的说法,这不是一个错误。 tell 根本不像你想的那样做。更新了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2017-11-11
    相关资源
    最近更新 更多