Python 使用来自多处理器模块的管理器更新嵌套dict
我一直在尝试使用多处理更新嵌套字典 如果字典包含元素列表,我可以添加我想要的信息,但是如果它是嵌套字典,我看不到任何更改 我知道多处理模块说它是一个dictproxy而不是dict,我试着改变模块上的示例来实现它,但我没有任何运气Python 使用来自多处理器模块的管理器更新嵌套dict,python,dictionary,multiprocessing,Python,Dictionary,Multiprocessing,我一直在尝试使用多处理更新嵌套字典 如果字典包含元素列表,我可以添加我想要的信息,但是如果它是嵌套字典,我看不到任何更改 我知道多处理模块说它是一个dictproxy而不是dict,我试着改变模块上的示例来实现它,但我没有任何运气 import socket import csv from pprint import pprint from multiprocessing import Pool,Process,current_process,Manager def dns_lookup(ag
import socket
import csv
from pprint import pprint
from multiprocessing import Pool,Process,current_process,Manager
def dns_lookup(aggregate,ip):
try:
hostname=socket.gethostbyaddr(ip)[0]
proc_name = current_process().name
#print(str(hostname) + " extracted from ip " + str(ip) + " by process id: " + str(proc_name) )
aggregate[ip]+=hostname
except Exception as e:
pass
if __name__=='__main__':
procs=[]
manager=Manager()
aggregate=manager.dict()
with open("ip_list.csv","r") as ipfile:
csv_reader=csv.reader(ipfile)
for index,row in enumerate(csv_reader):
if index == 0:
pass
else:
aggregate[row[0]]=row[1:]
#ips.append((row[0]))
proc = Process(target=dns_lookup, args=(aggregate,row[0],))
procs.append(proc)
proc.start()
for proc in procs:
proc.join()
pprint(dict(aggregate))
上面的代码可以工作,但如果我尝试将原始dict更改为
aggregate[row[0]]={'Other Items':row[1:]}
然后尝试将其更新为
d['hostname']=hostname
aggregate[ip]=d
#aggregate[ip]+=d
没有任何效果
我需要实际的列表有一个字典,而不是元素列表
当前文件很小,但我必须将其扩展到大约10k个查找,因此需要进行多处理
非常感谢您的帮助
谢谢,
Karan是的,
dict
上的更新似乎没有传播到其他进程。即使将内部dict迁移到manager.dict()
也不能解决问题。如果您从头开始创建一个新的dict并将其应用于聚合[ip]:
aggregate[ip] = {"hostname": hostname, "Other Items": aggregate[ip]['Other Items']}
这可能是一个bug,但我建议您在代码中做更大的更改。有两个缺点:
聚合
作为仍然需要查找的IP的“队列”和进程写入的结果容器。如果将其拆分为一个队列,一个只保存结果的dict可以避免您遇到的问题:那么,您只从队列中读取,而只写入结果容器聚合
多个核心进程。在Linux上,您将浪费大量不需要的内存。在Windows上,您可以从头开始启动1000个python程序。使用池
,让python计算出内核的数量,并将您的工作分布到这些进程中
import socket
import csv
from pprint import pprint
from multiprocessing import Pool, Queue, Process, current_process, Manager
from time import sleep
def dns_lookup(aggregate,queue):
while not queue.empty(): # live as long there are items in the queue
row = queue.get()
ip = row[0]
other_items = row[1:]
hostname=socket.gethostbyaddr(ip)[0]
aggregate[ip] = {
"hostname": hostname,
"other items": other_items,
"process_name": current_process().name}
if __name__=='__main__':
procs=[]
manager=Manager()
aggregate=manager.dict()
queue = Queue()
with open("ip_list.csv","r") as ipfile:
csv_reader=csv.reader(ipfile)
next(csv_reader) # instead of the if index == 0; pass
for row in csv_reader: # fill queue before starting any processes
queue.put(row)
# start x processes, where None says to take x = the number of cpus returned by `cpu_count()`
pool = Pool(None, dns_lookup, (aggregate, queue))
pool.close() # signal that we won't submit any more tasks to pool
pool.join() # wait until all processes are done
pprint(dict(aggregate))
此外:您最好使用
线程
而不是多处理
,因为您的进程将被网络而不是CPU阻塞。只有当您可以将一个CPU核心占用到100%时,多处理才有意义。我意识到使用进程并不是最好的方法,所以我切换到进程Pool
,只使用Proc.apply_async
来完成工作。然后,我开始按照您的建议研究线程,并将池从多处理模块更改为线程池。虽然在内存和CPU利用率方面效率更高,但我确实看到线程池需要更长的时间。实际上,这比使用进程池要花两倍的时间。有趣的是,多进程方法更快。如果我的回答回答了你所有的问题:你能投票/接受吗?否则,请询问还缺少什么