Python Multiprocessing DictProxy append to dict of list not working
我正在编写一个使用multiprocessing.managers.DictProxy的程序。 程序遍历目录,并创建一个dict,其中username是
1 | {'root': ["/boot/vmlinuz","/boot/grub"], 'testuser': ["/home/testuser","/home/testuser/.bashrc"]} |
我写的代码就是这样做的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/usr/bin/python import os import multiprocessing import sys import pwd import grp manager_attributes = multiprocessing.Manager() file_stats_user = manager_attributes.dict() def filestat(file): try: stat = os.stat(file) user = pwd.getpwuid(stat[4])[0] group = grp.getgrgid(stat[5])[0] if user not in file_stats_user: file_stats_user[user] = [] file_stats_user[user].append(file) except OSError, e: print e try: cores = (multiprocessing.cpu_count()*2) except: cores = 8 print"Starting parallel execution with", cores,"concurrency" pool_get_attributes = multiprocessing.Pool(cores) pool_get_attributes.map(filestat, files) pool_get_attributes.close() pool_get_attributes.join() |
其中files是获得的所有文件的列表。
但是,当我打印file_stats_user这是一个multiprocessing.managers.DictProxy对象时,我得到了键,但列表值为空,如
1 | {'root': [], 'testuser': []} |
我在这做错了什么?
谢谢。
如果两个进程在同一时间更新同一用户的dict,则编辑先前的解决方案具有竞争条件
您的解决方案不起作用,因为默认情况下,列表是当前进程的本地列表,并且对其进行的更新未被代理。
为了使其正常工作,您应该使用一个代理列表,以便在所有过程中进行更新
更换
1 | file_stats_user[user] = [] |
通过
1 | file_stats_user[user] = manager_attributes.list() |
现在,当您附加到列表时,它在所有进程中都是相同的
但是使用共享对象是进行多进程的一种不好的方法
更好的方法是收集每个呼叫的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from collections import defaultdict def filestat(file): try: stat = os.stat(file) user = pwd.getpwuid(stat[4])[0] group = grp.getgrgid(stat[5])[0] return user, file except OSError, e: print e return None try: cores = (multiprocessing.cpu_count()*2) except: cores = 8 print"Starting parallel execution with", cores,"concurrency" pool_get_attributes = multiprocessing.Pool(cores) result_map = pool_get_attributes.map(filestat, files) result = defaultdict(list) for user,file in (r for r in result_map if r is not None): result[user].append(file) pool_get_attributes.close() pool_get_attributes.join() |