2013-05-18 48 views
2

我試圖打開日本最新的維基百科數據庫在Linux上閱讀在Python 3.3.1,但我得到一個Segmentation fault (core dumped)誤差這套短節目:讀一個6.9GB文件會導致分段錯誤

with open("jawiki-latest-pages-articles.xml") as f: 
    text = f.read() 

文件本身是相當大的:

-rw-r--r-- 1 fredrick users 7368183805 May 17 20:19 jawiki-latest-pages-articles.xml 

因此它似乎有一個上限,我有多長的字符串可以存儲。解決這種情況的最佳方法是什麼?

我的最終目標是計算文件中最常見的字符,有點像現代版本的Jack Halpern的「報紙上最常用的漢字」。 :)

+5

你的機器有多少內存? – BlackVegetable

+1

其他人正在解決你的迭代問題 - 顯然最好是逐行讀取,而不是試圖在一個字符串中保存6+ GB。要計算字符,請查看標準庫的計數器:http://docs.python.org/2/library/collections.html#collections.Counter –

+0

有點偏離主題:沒有使用gzip壓縮的任何特定原因,for例? XML壓縮得很好,對於這樣一個非常大的文件,你可以通過壓縮來節省3到4GB。然後你可以用'gzip.open'打開它,就像你在這裏使用'open'一樣,gzip也可以快速解壓,所以性能可以接受(甚至可能比未壓縮的更快)。 – kampu

回答

11

不要一次閱讀整篇文章。即使您的Python發行版被編譯爲64位程序(在32位程序中分配超過4 GB的虛擬內存根本不可能),並且即使您有足夠的RAM來存儲它,它仍然是一個糟糕的想法立即將它們全部讀入內存。

一個簡單的選擇是在每次讀取它的線,並處理每一行:

with open("jawiki-latest-pages-articles.xml") as f: 
    for line in f: 
     # Process one line 

或者,也可以在固定大小的塊處理它:

while True: 
    data = f.read(65536) # Or any other reasonable-sized chunk 
    if not data: 
     break 
    # Process one chunk of data. Make sure to handle data which overlaps 
    # between chunks properly, and make sure to handle EOF properly 
+0

非常感謝。我沒有意識到'for'在文件對象上的工作方式。這是非常有用的信息。 –

+1

另請注意,如果您想將其作爲XML進行處理,您可以使用基於流的XML解析器,如['xml.sax'包]中提供的解析器(http://docs.python.org/2/庫/ xml.sax.html#模塊xml.sax)。但是對於只計算文件中的字符(包括XML標籤),您並不需要。 –

0

這是我最終使用的程序,如果任何人都好奇。

from collections import Counter 

counter = Counter() 

progress = 0 
with open("jawiki-latest-pages-articles.xml") as f: 
    for line in f: 
     progress += 1 
     counter.update(line) 
     if not progress%10000: print("Processing line {0}..., number {1}".format(line[:10], progress)) 

output = open("output.txt", "w+") 

for k, v in counter.items(): 
    print("{0}\t{1}".format(k, v), file=output) 

output.close() 
+0

您可以使用['enumerate()'](http://docs.python.org/2/library/functions.html#enumerate)獲取索引。 –