2017-06-15 129 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字典的每个文件。文件逐行读取,从不完全读取。所以需要一些时间,但不要太多记忆。