Python 使用来自多处理器模块的管理器更新嵌套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

我一直在尝试使用多处理更新嵌套字典

如果字典包含元素列表,我可以添加我想要的信息,但是如果它是嵌套字典,我看不到任何更改

我知道多处理模块说它是一个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))
上面的代码可以工作,但如果我尝试将原始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可以避免您遇到的问题:那么,您只从队列中读取,而只写入结果容器
    聚合
  • 如果您的csv文件中有1000行,那么最终将有1000个进程,而您的计算机一次只能切断
    多个核心进程。在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利用率方面效率更高,但我确实看到线程池需要更长的时间。实际上,这比使用进程池要花两倍的时间。有趣的是,多进程方法更快。如果我的回答回答了你所有的问题:你能投票/接受吗?否则,请询问还缺少什么