我一直在尝试使用多处理来更新嵌套字典。
如果字典包含元素列表,我可以添加我想要的信息,但如果它是嵌套字典,我看不到任何变化。
我知道多处理模块说它是dictproxy而不是dict而且我已经尝试更改模块上的示例来实现它但我没有运气。
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))
以上代码有效,但如果我尝试将原始字典更改为
aggregate[row[0]]={'Other Items':row[1:]}
然后尝试将其更新为
d['hostname']=hostname
aggregate[ip]=d
#aggregate[ip]+=d
没有任何影响。
我需要为实际列表提供字典而不是元素列表。
当前文件很小但我必须将其扩展到大约10k查找,因此需要进行多处理。
非常感谢任何帮助。
谢谢, 卡兰
答案 0 :(得分:2)
是的,似乎dict
上的更新未传播到其他进程。即使将内部词典迁移到manager.dict()
也无法解决问题。如果您从头开始创建一个新的dict并将其应用于aggregate[ip]
:
aggregate[ip] = {"hostname": hostname, "Other Items": aggregate[ip]['Other Items']}
这可能是一个错误,但我建议您对代码进行更大的更改。有两个缺点:
aggregate
作为"队列"仍需要查找的IP,以及进程写入的结果容器。如果将其拆分为一个队列,并且只保存结果的dict可以避免您遇到的问题:那么,您只能从队列中读取并只写入结果容器aggregate
。number-of-cores
个进程。在Linux上,你浪费了大量不需要的内存。在Windows上,你可以从头开始1� 000 python程序。改为使用Pool
让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))
此外:您最好使用Threads
而不是multiprocessing
,因为您的进程将被网络而不是CPU阻止。如果您可以将一个CPU核心占用到100%,那么多处理才有意义。