簡體   English   中英

在大文件Python上執行多處理的最佳方法

[英]Best way to perform multiprocessing on a large file Python

我有一個python腳本,它將遍歷一個列表(> 1000個元素),在一個大文件中找到變量,然后輸出結果。 我正在讀取整個文件> 1000次。 我嘗試使用多處理,但沒有太大幫助。 這是我想做的事情:

import gzip
from multiprocessing.pool import ThreadPool as Pool

def getForwardIP(clientIP, requestID):
   with gzip.open("xyz.log") as infile:
     for lines in infile:
        line= lines.split(" ")
        myRequestID= line[0]
        forwardIP= line[1]
        if myRequestID==requestID:
           print forwardIP
if __name__== "__main__":
    pool_size=8
    pool= Pool(pool_size)
    request_id_list= list()
    #request_id_list contains >1000 elements
    for id in request_id_list:
      pool.apply_async(getForwardIP, ("1.2.3.4.", id, ))
   pool.close()
   pool.join()

有沒有更快的方法? 任何幫助將不勝感激。 謝謝!

編輯

(我在這里輸入我的完整代碼)謝謝大家的建議。 現在,我將文件寫入列表,而不是讀取1000次。 我試圖對for循環進行多進程處理,但沒有成功。 下面是代碼:

import gzip
import datetime
from multiprocessing.pool import ThreadPool as Pool

def getRequestID(r_line_filename):
  requestIDList= list()
  with gzip.open(r_line_filename) as infile:
  #r_line_filename is a file with request_id and client_ip
    for lines in infile:
        line= lines.split(" ")
        requestID= line[1].strip("\n")
        myclientIP= line[0]
        if myclientIP==clientIP:
            requestIDList.append(requestID)  
   print "R line List Ready!"
   return(requestIDList)  



def getFLineList(fFilename):
   fLineList= list()
   with gzip.open(fFilename) as infile:
   #fFilename is a file with format request_id, forward_ip, epoch time
     for lines in infile:
        fLineList.append(lines.split())
  print "F line list ready!"
  return(fLineList)

def forwardIP(lines, requestID):
 myrequestID= lines[0]
 forwardIP= lines[1]
 epoch= int(lines[2].split(".")[0])
 timex= datetime.datetime.fromtimestamp(epoch).strftime('%Y-%m-%d %H:%M:%S')
 if myrequestID==requestID:
    print "%s %s %s"%(clientIP, timex, forwardIP)

if __name__== "__main__":
 pool= Pool()
 clientIP= "x.y.z.a"
 rLineList= getRequestID("rLine_subset.log.gz")
 fLineList= getFLineList("fLine_subset.log.gz")
 for RID in rLineList:
    for lines in fLineList:
        pool.apply_async(forwardIP, (lines, RID,))
    pool.close()
    pool.join()

多處理部分無法正常工作。 實際上,這一步要慢得多。 如果我不進行多重處理而只是遍歷列表,則速度會更快。 謝謝您的幫助!

我同意mwm314,您不應將文件讀取1000次。

我假設您沒有提供完整的代碼,因為client_ip參數似乎尚未使用,但是在這里,我將其重寫為僅打開文件一次,並且僅迭代文件中的每一行。 我還修改了getForwardIP以獲取請求ID的列表,並立即將其轉換為一組以獲得最佳查找性能。

import gzip


def getForwardIP(client_ip, request_ids):
    request_ids = set(request_ids)  # to get O(1) lookup
    with gzip.open("xyz.log") as infile:
        for lines in infile:
            line = lines.split(" ")
            found_request_id = line[0]
            found_forward_ip = line[1]
            if found_request_id in request_ids:
                print found_forward_ip


if __name__ == "__main__":
    request_id_list = list()
    # request_id_list contains >1000 elements
    getForwardIP("1.2.3.4.", request_id_list)

確實有更快的方法。 不要在1000次內讀取和解析文件。 而是一次讀一次,解析一次,然后存儲。 文件I / O是您可以執行的最慢的操作之一(使用任何語言)。 在內存中處理要快得多!

像這樣的東西(因為我沒有訪問"xyz.log"未經測試。)對於鷹派:很明顯,我也沒有配置它,但是我有一個偷偷摸摸的懷疑,一次讀取文件比讀取文件快1000次):

import gzip

def readFile():
  my_lines = []
  with gzip.open("xyz.log") as infile:
     for lines in infile:
        line = lines.split(" ")
        my_lines.append(line)

  return my_lines

def getForwardIp(lines, requestID): #Doesn't look like you need client IP (yet), so I nuked it
  myRequestID= line[0]
  forwardIP= line[1]
  if myRequestID==requestID:
     print forwardIP

if __name__ == "__main__":
  parsed_lines = readFile()
  request_id_list= list()
  #request_id_list contains >1000 elements
  for id in request_id_list:
    getForwardIp(parsed_lines, requestID)

我可能會在單個大文件中掃描所有請求的ID,然后充分利用ThreadPool調用getForwardIP()

您可以將單個大文件划分為多個區域,並讓多個工作進程處理文件的不同分區,但是這種方法存在一些挑戰,可能無法在所有文件系統上使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM