2014-09-19 53 views
3

我有這樣的方法:的Python:在文件求EOL不工作

def get_chunksize(path): 
    """ 
    Breaks a file into chunks and yields the chunk sizes. 
    Number of chunks equals the number of available cores. 
    Ensures that each chunk ends at an EOL. 
    """ 
    size = os.path.getsize(path) 
    cores = mp.cpu_count() 
    chunksize = size/cores # gives truncated integer 

    f = open(path) 
    while 1: 
     start = f.tell() 
     f.seek(chunksize, 1) # Go to the next chunk 
     s = f.readline() # Ensure the chunk ends at the end of a line 
     yield start, f.tell()-start 
     if not s: 
      break 

它應該打破一個文件分割成塊並返回塊(以字節爲單位)的開始和塊大小。

至關重要的是,塊的末尾應該對應於行的末尾(這就是爲什麼f.readline()行爲存在的原因),但是我發現我的塊根本不在尋找EOL。

該方法的目的是,以便然後讀其可以被傳遞給一個csv.reader實例(通過StringIO),用於進一步的處理塊。

我一直無法發現任何明顯錯誤的功能......任何想法,爲什麼它不移動到EOL?

我想出了這個非常笨拙的選擇:

def line_chunker(path): 
    size = os.path.getsize(path) 
    cores = mp.cpu_count() 
    chunksize = size/cores # gives truncated integer 

    f = open(path) 

    while True: 
     part = f.readlines(chunksize) 
     yield csv.reader(StringIO("".join(part))) 
     if not part: 
      break 

這將分割文件與每個塊的CSV讀者塊,但最後一塊始終是空的(?),並具有參加一連串的字符串相當笨拙。

+0

我的第一個猜測是'.readline()'使用了一個緩衝區。這意味着它總是讀取4096字節,然後返回第一行。 – 2014-09-19 14:07:32

+0

如果使用緩衝區,是不是會在返回行之前回溯到EOL字符所在的位置,以便後續調用f.tell()會給出正確的位置?無論如何,這種行爲肯定是必需的,所以'.readline'總是從行首讀取(多次調用時)。 – jramm 2014-09-19 14:12:47

+0

將'chunksize'設置爲小(1或10)。上面的代碼應該逐行讀取輸入。你看到'f.tell()'在'f.readline()'之後返回一個模式嗎? – 2014-09-19 14:15:21

回答

1
if not s: 
     break 

而不是看s,看看你在文件末尾,你應該看看,如果你已經使用到了文件的末尾:

if size == f.tell(): break

這應該解決它。我不會依賴於每行只有一條記錄的CSV文件。

first,last,message 
sue,ee,hello 
bob,builder,"hello, 
this is some text 
that I entered" 
jim,bob,I'm not so creative... 

通知第二記錄(BOB)橫跨3條線路跨越:我已經有新的線串幾個CSV文件的工作。 csv.reader可以處理這個。如果這個想法是在csv上做一些cpu密集型工作。我會創建一個線程數組,每個線程都有n個記錄的緩衝區。讓csv.reader使用循環法向每個線程傳遞一條記錄,如果其緩衝區已滿,則跳過一條線程。
希望這有助於 - 享受。