2013-04-10 61 views
10

我在Windows 64位上使用Python 3.3.0。Python file.tell()給奇怪的數字?

我有一個文本文件,如下圖所示:(見底部在主人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 

與18446744073709551714爲3號線是什麼?雖然它看起來像一個不可能的值,但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

回答

8

這是一個由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評論。


有在與這條巨蟒的bug跟蹤系統的issue,並通過克特林Iacob最後的評論是:

我試圖重現此,拿起我的磁盤上的文件,事實上我一個 負數,但該文件具有Unix行尾。這是 記錄在http://docs.python.org/2/library/stdtypes.html#file.tell 所以可能沒有什麼可做的。

至於阿明在msg180145報告,即使它不直觀, 此相匹配的Windows FTELL的行爲,如在 http://msdn.microsoft.com/en-us/library/0ys3hc0b%28v=vs.100%29.aspx備註 部分記錄。 fileobjects上的tell()方法明確記錄爲匹配 ftell行爲:「返回文件的當前位置,如stdio的 ftell()」。所以即使它根本不直觀,也可能更好地保留原樣。 tell()返回直觀的非零 位置,當在Python3上打開'a'時和在Python 2.7上打開時使用 io.open,因此它對於未來是固定的。

所以它看起來像一個「wontfix」錯誤。 有人應該可能會提出一個問題(評論該問題),因爲在python3文檔中根本沒有提及這個事實。


根據Antoine Pitrou python3不使用ftell()可言,因此這似乎是一個不同的錯誤。同樣的錯誤是不python3.2.3可重複和固定的時候大概介紹了該issue(至少,這是我能找到tell()之間3.2.3 3.3實施的唯一的變化)


最後修改:根據io模塊文檔tell方法確實不是返回自文件開始以來的字節數。返回的值是一個「不透明數字」,這意味着您可以使用它的唯一方法是將其傳遞給seek以恢復該位置。其他操作無意義。事實上,直到python3.2.3返回值是你所期望的只是一個實現細節。

請注意,文檔中this部分的信息僅僅是錯誤,並且希望它將在未來得到修復。

+0

呃,等等,這個文本文件是用記事本創建的。使用記事本2和行結尾顯示,我看到CR + LF,這是窗口行結束吧? Unix的行結尾只有LF纔對? 經過我的測試文件修改後,顯然,更長的線條更容易得到這個問題。 – Eric 2013-04-11 04:53:46

+0

@Eric是否嘗試從Python中以二進制模式打開文件並查看內容?另外,你可以發佈文件內容/上傳文件,以便我們可以測試嗎? AFAIK礦是唯一明智的解釋,並且我堅信Python的文件是正確的,所以我仍然認爲問題在於對'ftell()'的底層調用返回垃圾。 – Bakuriu 2013-04-11 05:36:18

+0

我用二進制模式編輯了原來的問題,並在mediafire中上傳了文本文件。 – Eric 2013-04-11 13:39:06