我在Windows 64bit上使用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)
是一个可接受的值,显然确实将我带到了第3行的末尾。虽然,我似乎无法弄清楚原因。
编辑:
以二进制模式打开不会导致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
答案 0 :(得分:10)
这是由UNIX样式的行结尾引起的记录行为:
返回文件的当前位置,例如
stdio
的{{1}}。注意:在Windows上,
ftell()
在读取带有Unix样式的行结尾的文件时可以返回非法值(在tell()
之后)。使用二进制模式 ('rb')来解决这个问题。
以上文档摘自python2.7.4文档。 python3的文档稍有改动,因为现在有一个处理I / O的类层次结构,我找不到这些信息。您的测试显示该行为无论如何都没有改变。此外,python3.3的源代码在fgets()
调用的函数之前有XXX Windows support below is likely incomplete
注释。
python bug跟踪器中有一个issue与此相关,Catalin Iacob的最终评论是:
我试图重现这个,在我的磁盘上挑选了一个文件,确实我得到了一个 负数,但该文件有Unix行结尾。这是 记录在http://docs.python.org/2/library/stdtypes.html#file.tell 所以可能那时无事可做。
关于Armin在msg180145中的报告,即使它不直观, 这与ftell在Windows上的行为相匹配,如备注中所述 部分 http://msdn.microsoft.com/en-us/library/0ys3hc0b%28v=vs.100%29.aspx。 fileobjects上的tell()方法明确记录为匹配 ftell行为:“返回文件的当前位置,就像stdio一样 ftell()“。所以即使它根本不直观,也可能 最好保持原样。 tell()返回直观的非零值 使用时在Python3和Python 2.7上使用'a'打开时的位置 io.open所以无论如何它都是固定的。
所以它似乎是一个“wontfix”错误。 有人应该打开一个问题(评论问题),因为在python3文档中根本没有提到这个事实。
根据Antoine Pitrou python3根本不使用tell
,因此这似乎是一个不同的错误。此错误在python3.2.3中不可重现,并且可能在修复此issue时引入(至少,它是我在3.2.3和3.3之间可以找到ftell()
实现的唯一更改)< / p>
上次编辑:根据io
模块文档,tell()
方法不返回自文件开头以来的字节数。返回值是一个“不透明数字”,这意味着您可以使用它的唯一方法是将其传递给tell
以返回该位置。其他操作没有意义。事实上,直到python3.2.3返回的值是你所期望的只是一个实现细节。
请注意,文档this部分中的信息只是错误,希望将来能够修复。