2011-06-02 55 views
12

我正在處理一個Python腳本以處理兩個文件 - 一個包含UUID列表,另一個包含大量日誌條目 - 每行包含另一個文件中的一個UUID。該程序的目的是從file1創建一個UUIDS列表,然後每次在日誌文件中找到UUID時,每找到一個匹配就增加相關值。Python中用於遍歷大文件(10GB +)的最有效方式

這麼長的故事,請記下每個UUID在日誌文件中出現的次數。 目前,我有一個以UUID作爲關鍵字填充的列表,並且'命中'作爲值。然後再循環遍歷日誌文件的每一行,並檢查日誌中的UUID是否與UUID列表中的UUID匹配。如果匹配,則增加該值。

for i, logLine in enumerate(logHandle):   #start matching UUID entries in log file to UUID from rulebase 
     if logFunc.progress(lineCount, logSize): #check progress 
      print logFunc.progress(lineCount, logSize) #print progress in 10% intervals 
     for uid in uidHits: 
      if logLine.count(uid) == 1:    #for each UUID, check the current line of the log for a match in the UUID list 
       uidHits[uid] += 1     #if matched, increment the relevant value in the uidHits list 
       break        #as we've already found the match, don't process the rest 
     lineCount += 1    

它的工作原理應該如此 - 但我相信有更高效的文件處理方式。我已經通過一些指南,發現使用'count'比使用編譯正則表達式更快。我認爲以塊爲單位而不是逐行讀取文件可以通過減少磁盤I/O時間來提高性能,但在測試文件上的性能差異〜200MB是可以忽略的。如果任何人有任何其他方法,我會非常感謝:)

+2

無論您實際讀取的區塊的大小如何,通常都會緩衝文件I/O。 – delnan 2011-06-02 13:59:26

+3

它需要更高效嗎?多久時間?你需要多長時間?您可能已經達到了您的存儲(磁盤)的性能限制,在這種情況下,您的Python腳本的速度有多快並不重要。 – 2011-06-02 14:05:35

+0

它現在正在運行一個測試文件 - 它是通過10GB文件的一半,大約需要30分鐘。作爲我第一次出場的Python,我不知道這是快還是慢。沒有要求它在x分鐘內完成,但速度更快;) – SG84 2011-06-02 14:09:49

回答

14

功能性地思考!

  1. 編寫一個函數,它會取一行日誌文件並返回uuid。說它叫uuid

  2. 將此函數應用於日誌文件的每一行。如果您使用的是Python 3,則可以使用內置函數圖;否則,你需要使用itertools.imap。

  3. 將此迭代器傳遞給collections.Counter。

    collections.Counter(map(uuid, open("log.txt"))) 
    

這將是非常最爲有效的。

一對夫婦的評論:

  • 這完全忽略的UUID的名單,只是統計出現在日誌文件中的。如果你不想要這個,你需要修改程序。

    • 您的代碼很慢,因爲您使用的數據結構錯誤。字典是你想要的。
+0

感謝您的輸入 - 一旦這個測試運行完成,我得到我的資源,我會看看。我想我在一個字典上使用了一個列表,因爲我想維護UUIDS的順序,但我想我可以稍後使用列表作爲索引,然後從字典中提取相應的值? – SG84 2011-06-02 14:27:58

+5

@ SG84你可能會看到關於Python生成器的優秀文章http://www.dabeaz.com/generators/Generators.pdf,特別是處理大文件。你會開導:-) – OnesimusUnbound 2011-06-02 14:32:07

+0

我之前嘗試了一個發生器,在我從地板上拿起大腦並使其工作之後,性能增益與僅對文件使用for循環沒有多大區別。感謝您的鏈接,但這一切都使得良好的閱讀 – SG84 2011-06-02 14:41:57

3

你試過mincemeat.py?它是MapReduce分佈式計算框架的Python實現。我不確定你是否會有性能提升,因爲在使用之前我還沒有處理過10GB的數據,儘管你可能會探索這個框架。

4

和上面的人一樣,用10GB的文件,你可能會很快達到磁盤的極限。對於僅有代碼的改進,生成器建議非常好。在蟒蛇2.x它看起來像

uuid_generator = (line.split(SPLIT_CHAR)[UUID_FIELD] for line in file) 

這聽起來像這實際上不必是一個python問題。如果你沒有比計算UUID更復雜,Unix可能能夠比python更快地解決你的問題。

cut -d${SPLIT_CHAR} -f${UUID_FIELD} log_file.txt | sort | uniq -c 
0

嘗試測量大部分時間都花在,使用分析http://docs.python.org/library/profile.html

哪裏最大限度地優化取決於數據的性質:如果UUID的列表不是很長,你可能會發現例如,大部分時間花費在「if logFunc.progress(lineCount,logSize)」上。如果列表非常長,您可以幫助將uidHits.keys()的結果保存到循環外的變量並遍歷該變量,而不是字典本身,但Rosh Oxymoron建議首先找到該id,然後檢查它是否在uidHits可能會幫助更多。

在任何情況下,您都可以取消lineCount變量,並使用i代替。如果線路很長,則find(uid) != -1可能會比count(uid) == 1更好。

相關問題