在大文件Python上执行多处理的最佳方法
我有一个python脚本,它将遍历>1000个元素的列表,在一个大文件中找到变量,然后输出结果。我正在读取整个文件>1000次。我尝试使用多处理,但没有多大帮助。 以下是我正在尝试做的:在大文件Python上执行多处理的最佳方法,python,multiprocessing,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 lin
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()
多处理部件不工作。实际上,这个要慢得多。如果我不进行多重处理,只遍历列表,速度会更快。提前谢谢你的帮助 确实有一种更快的方法。不要在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)
确实有一种更快的方法。不要在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,然后充分利用线程池调用getForwardIP
您可以将单个大文件划分为多个区域,并让多个工作进程处理文件的不同分区,但这种方法存在一些挑战,可能无法在所有文件系统上运行。我可能会在单个大文件中扫描所有请求的ID,然后充分利用线程池调用getForwardIP
您可以将单个大文件划分为多个区域,并让多个工作人员处理文件的不同分区,但这种方法存在一些挑战,可能无法在所有文件系统上运行。我同意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)
我同意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)
为什么不在脚本开始时读取文件,并使用字典或列表。每次调用getForwardIP时,都会从头开始读取文件。我不认为这样做有什么意义,如果文件太大,无法在内存中容纳request_id->ip map,您可以使用这里描述的技术,在收集的一组偏移量上运行每个进程,为什么不在脚本开始时读取文件,并使用字典或列表。每次调用getForwardIP时,都会从头开始读取文件。我不认为这样做有什么意义,如果文件太大,并且无法在内存中容纳request\u id->ip映射,您可以使用这里描述的技术,在收集的一组偏移上运行每个进程。谢谢!由于文件太大,我们是否有可能无法将整个内容存储在内存/列表中?如果是这样的话,您将经历一段艰难的时光。你有两个选择。您可以使用AWS/Spark之类的工具为一次性工作获取更多内存,也可以购买更大的机器。或者,如果请求\u id\u列表的顺序与它们在使用yield关键字的文件中的显示顺序相同,则可以使用生成器而不是返回列表。这是实际情况吗?它不适合记忆吗?如果不重要的话,不要太多地使用理论;它确实适合内存,但在这种情况下。我担心的是,如果我必须处理更大的文件,我肯定必须这样做,那么还有什么其他选择呢。对于这一个,您的解决方案起了作用。谢谢谢谢由于文件太大,我们是否有可能无法将整个内容存储在内存/列表中?如果是这样,您将
过得不愉快。你有两个选择。您可以使用AWS/Spark之类的工具为一次性工作获取更多内存,也可以购买更大的机器。或者,如果请求\u id\u列表的顺序与它们在使用yield关键字的文件中的显示顺序相同,则可以使用生成器而不是返回列表。这是实际情况吗?它不适合记忆吗?如果不重要的话,不要太多地使用理论;它确实适合内存,但在这种情况下。我担心的是,如果我必须处理更大的文件,我肯定必须这样做,那么还有什么其他选择呢。对于这一个,您的解决方案起了作用。谢谢对这不是全部代码。将列表设置为帮助。在不同进程中调用列表的每个元素会进一步优化它吗?您的意思是在线程池中的request\u id中找到request\u id时运行?你可以试试!由于集合上的非写操作是线程安全的,我认为它不会造成任何伤害。是的!请参考编辑手册。我已经发布了全部代码。在你的新代码中,我有一种预感,瓶颈现在是stdout。如果您在Unix系统上,请尝试使用python yourscript.py>output_file.txt在shell/Terminal中运行脚本。我正在使用相同的方法运行脚本。是的!这不是全部代码。将列表设置为帮助。在不同进程中调用列表的每个元素会进一步优化它吗?您的意思是在线程池中的request\u id中找到request\u id时运行?你可以试试!由于集合上的非写操作是线程安全的,我认为它不会造成任何伤害。是的!请参考编辑手册。我已经发布了全部代码。在你的新代码中,我有一种预感,瓶颈现在是stdout。如果您在Unix系统上,请尝试使用python yourscript.py>output_file.txt在shell/Terminal中运行脚本。我正在使用相同的方法运行脚本。这就是我现在要做的。在不同的进程中调用gerForwardIP。谢谢这就是我现在要做的。在不同的进程中调用gerForwardIP。谢谢