2013-02-14 123 views
2

我想通過csv文件閱讀時,我正在查找的百分比。我知道如何使用tell()和文件對象來做到這一點,但是當我使用csv.reader讀取該文件對象時,然後對我的reader對象中的行執行for循環,tell()函數總是返回它在文件的末尾,無論我在循環中的哪個位置。我怎樣才能找到我的位置?蟒蛇csv扭曲告訴

當前代碼:

with open(FILE_PERSON, 'rb') as csvfile: 
    spamreader = csv.reader(csvfile) 
    justtesting = csvfile.tell() 
    size = os.fstat(csvfile.fileno()).st_size 
    for row in spamreader: 
     pos = csvfile.tell() 
     print pos, "of", size, "|", justtesting 

我扔「justtesting」在那裏只是爲了證明告訴()不會返回0,直到我開始我的for循環。

這將爲我的csv文件中的每一行返回相同的結果: 579 of 579 | 0

我在做什麼錯?

回答

3

csv庫在讀取文件時使用了緩衝區,所以文件指針跳轉到較大的塊中。它不是而是逐行讀取你的文件。

它讀取較大塊中的數據以使解析更容易,並且由於換行符可能嵌入在引號中,因此逐行讀取CSV數據將不起作用。

如果你有給出進度報告,那麼你需要預先計算行數。如果輸入CSV文件並不在列值中嵌入換行符下才起作用:

with open(FILE_PERSON, 'rb') as csvfile: 
    linecount = sum(1 for _ in csvfile) 
    csvfile.seek(0) 
    spamreader = csv.reader(csvfile) 
    for line, row in enumerate(spamreader): 
     print '{} of {}'.format(line, linecount) 

還有其他的方法來計算行(見How to get line count cheaply in Python?)的數量,但因爲你會閱讀文件反正將其作爲CSV進行處理,您也可以使用該文件的打開文件。我不確定是否將文件作爲內存映射打開,然後將其作爲普通文件再次讀取會更好。

+0

好的,這是有道理的,那麼有沒有什麼有效的方法來確定我有多遠?我知道我可以做rows = list(spamreader),然後對於rownum,列中的行(行):但我已經讀過,效率很低。還有其他訣竅嗎? – 2013-02-14 16:41:20

+0

@BlairConnolly:爲你添加一個。它*將*讀取整個文件以首先計算行數。 – 2013-02-14 16:42:08

+1

在調用'enumerate'之前,你不需要強制轉換爲'list' - 你可以在'enumerate(spamreader)'中進行行處理,這同樣有效。 – katrielalex 2013-02-14 16:42:31

0

csvreader文檔說:

... csvfile可以是支持迭代器協議及其每個next()方法被調用時返回字符串的任何對象...

因此一個小改動,OP原代碼:

import csv 
import os 
filename = "tar.data" 
with open(filename, 'rb') as csvfile: 
    spamreader = csv.reader(csvfile) 
    justtesting = csvfile.tell() 
    size = os.fstat(csvfile.fileno()).st_size 
    for row in spamreader: 
     pos = csvfile.tell() 
     print pos, "of", size, "|", justtesting 
############################################### 
def generator(csvfile): 
    # readline seems to be the key 
    while True: 
     line = csvfile.readline() 
     if not line: 
      break 
     yield line 
############################################### 
print 
with open(filename, 'rb', 0) as csvfile: 
    spamreader = csv.reader(generator(csvfile)) 
    justtesting = csvfile.tell() 
    size = os.fstat(csvfile.fileno()).st_size 
    for row in spamreader: 
     pos = csvfile.tell() 
     print pos, "of", size, "-", justtesting 

運行這個對我的測試數據給出了下面,顯示出兩個不同的應用程序蟑螂產生不同的結果。

224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 
224 of 224 | 0 

16 of 224 - 0 
32 of 224 - 0 
48 of 224 - 0 
64 of 224 - 0 
80 of 224 - 0 
96 of 224 - 0 
112 of 224 - 0 
128 of 224 - 0 
144 of 224 - 0 
160 of 224 - 0 
176 of 224 - 0 
192 of 224 - 0 
208 of 224 - 0 
224 of 224 - 0 

我置零緩衝的open,但它並沒有區別,事情是在發電機readline