我在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()经常弄清楚我的位置是什么。但是,当按如下所示读取文件的各行时,我得到一个非常奇怪的结果:
.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
第三行的18446744073709551714是怎么回事?尽管它看起来像一个不可能的值,f.seek(18446744073709551714)但显然是可以接受的值,确实使我到达了第三行的结尾。虽然,我似乎无法弄清楚为什么。
f.seek(18446744073709551714)
编辑:在二进制模式下打开不会出现任何问题tell():
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
这是由UNIX样式的行尾引起的已记录的行为:
file.tell() 返回文件的当前位置,喜欢stdio的ftell()。 注意 :在Windows上,当读取带有Unix样式的行尾的文件时,tell()可以返回非法值(在后面fgets())。使用二进制模式(’rb’)可以避免此问题。
file.tell()
返回文件的当前位置,喜欢stdio的ftell()。
stdio
ftell()
注意 :在Windows上,当读取带有Unix样式的行尾的文件时,tell()可以返回非法值(在后面fgets())。使用二进制模式(’rb’)可以避免此问题。
fgets()
以上文档取自python2.7.4文档。python3的文档有所更改,因为现在有了处理I / O的类层次结构,而我找不到这些信息。您的测试表明该行为始终没有改变。同样,python3.3的源代码在调用XXX Windows support below is likely incomplete的函数之前有一个注释tell。
XXX Windows support below is likely incomplete
tell
与此相关的python bug跟踪器中存在一个问题,Catalin Iacob的最终评论是:
我试图重现此错误,在磁盘上选择了一个文件,确实得到了一个负数,但是该文件具有Unix行尾。在http://docs.python.org/2/library/stdtypes.html#file.tell中对此进行了记录, 因此,那时可能没有任何事可做。 至于msg180145中Armin的报告,即使它不是很直观,也与ftell在Windows上的行为相匹配,如http://msdn.microsoft.com/zh- cn/library/0ys3hc0b%28v=vs.100的“备注”部分所述。 %29.aspx。文件对象上的tell()方法已明确记录为与ftell行为匹配:“返回文件的当前位置,如stdio的ftell()”。因此,尽管它根本不直观,但最好还是保留它。tell()在python.3和io.open上在Python 2.7上以’a’打开时返回直观的非零位置,因此无论如何它在将来都是固定的。
我试图重现此错误,在磁盘上选择了一个文件,确实得到了一个负数,但是该文件具有Unix行尾。在http://docs.python.org/2/library/stdtypes.html#file.tell中对此进行了记录, 因此,那时可能没有任何事可做。
至于msg180145中Armin的报告,即使它不是很直观,也与ftell在Windows上的行为相匹配,如http://msdn.microsoft.com/zh- cn/library/0ys3hc0b%28v=vs.100的“备注”部分所述。 %29.aspx。文件对象上的tell()方法已明确记录为与ftell行为匹配:“返回文件的当前位置,如stdio的ftell()”。因此,尽管它根本不直观,但最好还是保留它。tell()在python.3和io.open上在Python 2.7上以’a’打开时返回直观的非零位置,因此无论如何它在将来都是固定的。
因此,这似乎是一个“ wontfix”错误。 某人可能应该打开一个问题 (对此 问题进行了 评论),因为在python3文档中根本没有提到这个事实。
根据Antoine Pitrou的说法, python3根本不使用ftell(),因此这似乎是一个不同的错误。此外,该错误在python3.2.3中不可重现,并且可能是在解决此问题时引入的(至少,这是我只能tell()在3.2.3和3.3之间实现的唯一更改)
上次编辑:根据io模块文档,此tell方法自文件开头以来 不 返回字节数。返回的值是“不透明数字”,这意味着使用它的唯一方法是将其传递给seek该位置以返回该位置。其他操作没有意义。在python3.2.3之前返回的值就是您所期望的事实,但这只是实现细节。
io
seek
请注意,本文档此部分中的信息完全是 错误的 ,希望将来会得到修复。