在大型文件Python上执行多处理的最佳方法

时间:2017-02-22 23:30:11

标签: python multiprocessing

我有一个遍历列表的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()

多处理部分无法正常工作。实际上,这个慢得多。如果我不进行多处理并只是遍历列表,那就更快了。感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

我同意mwm314你不应该1000次阅读该文件。

我假设您没有给我们完整的代码,因为old_to_new={} old_to_new[old_name] = new_name 参数似乎未被使用,但在这里我已将其重写为仅打开文件一次并且仅通过迭代文件中的每一行一次。我还修改了saver = tf.Saver(old_to_new) saver.restore(filepath) 以获取请求ID列表,并立即将其转换为一组以获得最佳查找性能。

client_ip

答案 1 :(得分:1)

确实有更快的方法。不要在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)

答案 2 :(得分:1)

我可能会扫描单个大文件中的所有请求的ID,然后充分利用ThreadPool来调用getForwardIP()

您可以将单个大型文件分区为多个区域,并让多个工作人员处理该文件的不同分区,但这种方法存在一些挑战,可能无法在所有文件系统上运行。