2017-06-15 40 views
1

我有一個包含超過24,000,000行的大文件.txt。現在我想要做一個字數統計,即計算每個單詞及其相應的出現次數並將它們記錄到一個新文件中。下面是我試圖運行代碼:使用python讀寫大文件

import gensim 
class Corpus(gensim.corpora.TextCorpus): 
    def count_tokens(self): 
     word_count = 0 
     for text in self.get_texts(): 
      word_count += len(text) 
     return word_count 
    def get_texts(self): 
     for filename in self.input: 
      yield open(filename).read().split() 

def main(): 
    corpus = Corpus(['somefile.txt']) 
    word_count = corpus.count_tokens() 
    text = open('somefile.txt').read().split() 
    with open('path_to_output', 'w') as f: 
     for word, _ in corpus.dictionary.token2id.items(): 
      num_occur = text.count(word) 
      f.write('%s %d\n' % (word, num_occur)) 

if __name__ == '__main__': 
    main() 

而且服務器掛起...我不知道是否有其他足夠的方式這樣做,或者我可以做什麼改進?你如何用python讀寫真正大的文件?

+1

使用類似系統的標記器 - 解析char char,並檢查匹配項。當模棱兩可時,繼續查看下一個字符以決定是否有延續 – Uriel

+0

'open(filename).read()。split()'完全讀取文件,然後創建一個標記化版本:同時爲內存的兩倍。如果你只需要計數,Uriel方法可能是正確的。 –

回答

2

get_texts()方法一次讀取內存中的一個完整的文件。有很多小文件的語料庫沒問題,但如果你有一個巨大的文件,你需要逐行閱讀。

from collections import Counter 
wordcounts = Counter() 

with open("file.txt") as fp: 
    for line in fp: 
     wordcounts.update(line.split()) 
+0

如果文件只是一長串單詞會發生什麼?用足夠大的文件,這仍然會出現問題 – Uriel

+0

OMG,這種方法可以在幾分鐘內完成!拯救我的一天!謝謝! – user5779223

+0

@Uriel,每行一個字的工作原理是一樣的。如果文件中沒有換行符,則只會有問題。對於這種情況,您需要讀取字節塊,並修復損壞的單詞,甚至在邊緣處破壞多字節字符。顯然,插入一個可以做到這一點的庫會更容易。但顯然這是一個_text_文件,即換行符,所以不需要去那裏。 – alexis

0

我會做這樣的事情:

words = {} 
with open('somefile.txt', 'r') as textf: 
    for line in textf.readlines(): 
     for word in line.split(): 
      words[word] = words.getdefault(word, 0) + 1 

不是很Python的,但它的想法

+0

這沒有幫助,它仍然一次讀取內存中的整個文件。 – alexis

+0

,但在textf.readlines()中替換'for line:'用'在textf:中換行'應該會更好。它一次只能讀取1行,不需要其他更改。 –

+0

也使用'collections.Counter'會更好。 –

1

你的代碼有許多問題:

  • 讀取內存中的文件,然後拆分的話,那麼它加倍(或三倍)的內存大小
  • 它是兩次,第一次計數的單詞數,然後再以數每個字

我創建了一個簡單的例子,的發生沒有你的所有對象以及對象,在幾個文件中使用collections.Countertext_file_list保存文件路徑的列表。

import collections 

c = collections.Counter() 
for text_file in text_file_list: 
    with open(text_file) as f: 
     c.update(word for line in f for word in line.split()) 

該環路上的文件,並更新專業Counter字典的每個文件。文件逐行讀取,從不完全讀取。所以需要一些時間,但不要太多記憶。