【问题标题】:python - dictionary iterator for pool mappython - 用于池映射的字典迭代器
【发布时间】:2014-09-20 13:54:25
【问题描述】:

我正在处理一组frozensets。我正在尝试为字典“输出”中的每个冻结集找到最小集。我有 70k freezesets,所以我正在制作这个frozenset 字典并并行化这个任务。当我尝试将此字典作为输入传递给我的函数时,只发送密钥,所以我收到错误,有人可以帮我找出问题所在。

output => {frozenset({'rfid', 'zone'}): 0, frozenset({'zone'}): 0, frozenset({'zone', 'time'}): 0}

def reduce(prob,result,output):
    print(output)
    for k in output.keys():
    #Function to do something


def reducer(prob,result,output):
    print(output)
    p = Pool(4) #number of processes = number of CPUs
    func2 = partial(reduce,prob,result)
    reduced_values= p.map( func2,output,chunksize=4)
    p.close() # no more tasks
    p.join()  # wrap up current tasks
    return reduced_values

if __name__ == '__main__':
    final = reducer(prob,result,output)

{frozenset({'rfid', 'zone'}): 0, frozenset({'zone'}): 0, frozenset({'zone', 'time'}): 0}
frozenset({'rfid', 'zone'}) 
Error : AttributeError: 'frozenset' object has no attribute 'keys'

已按要求更新

from multiprocessing import Pool
from functools import partial
import itertools

output = {frozenset({'rfid', 'zone'}): 0, frozenset({'zone'}): 0, frozenset({'zone', 'time'}): 0}
prob = {'3': 0.3, '1': 0.15, '2': 0.5, '4': 0.05}
result = {'2': {frozenset({'time', 'zone'}), frozenset({'time', 'rfid'})}, '3': {frozenset({'time', 'rfid'}), frozenset({'rfid', 'zone'})}}

def reduce(prob,result,output):
    print(output)
    for k in output.keys():
        for ky,values in result.items():
            if any(k>=l for l in values):
                output[k] += sum((j for i,j in prob.items() if i == ky))
    return output


def reducer(prob,result,output):
    print(output)
    p = Pool(4) #number of processes = number of CPUs
    func2 = partial(reduce,prob,result)
    reduced_values= p.map( func2,output,chunksize=4)
    p.close() # no more tasks
    p.join()  # wrap up current tasks
    return reduced_values

if __name__ == '__main__':
    final = reducer(prob,result,output)


{frozenset({'zone', 'rfid'}): 0, frozenset({'zone'}): 0, frozenset({'time', 'zone'}): 0}
    for k in output.keys():
AttributeError: 'frozenset' object has no attribute 'keys'
frozenset({'zone', 'rfid'})

来自控制台的完整错误详情:

{frozenset({'zone', 'time'}): 0, frozenset({'zone', 'rfid'}): 0, frozenset({'zone'}): 0}
frozenset({'zone', 'time'})
multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "F:\Python34\lib\multiprocessing\pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "F:\Python34\lib\multiprocessing\pool.py", line 44, in mapstar
    return list(map(*args))
  File "C:\Users\Dell\workspace\key_mining\src\variable.py", line 16, in reduce
    for k in output.keys():
AttributeError: 'frozenset' object has no attribute 'keys'
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\***\variable.py", line 33, in <module>
    final = reducer(prob,result,output)
  File "C:\***\variable.py", line 27, in reducer
    reduced_values= p.map( func2,output,chunksize=4)
  File "F:\Python34\lib\multiprocessing\pool.py", line 260, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "F:\Python34\lib\multiprocessing\pool.py", line 599, in get
    raise self._value
AttributeError: 'frozenset' object has no attribute 'keys'

【问题讨论】:

  • 当您将p.map 应用于字典时,它会将其视为列表,因此会像 for 循环一样遍历键。你想把它传递给output.items() 并对每个元组做点什么吗?
  • 我想要整个字典输出 => {frozenset({'rfid', 'zone'}): 0, freezeset({'zone'}): 0, frozenset({'zone', 'time'}): 0} 在该函数内,然后我想迭代每个键值。但是我的疑问是,当我尝试在该函数中打印输出时,我得到的只是这个 frozenset({'rfid', 'zone'}) ,而不是 freezeset({'rfid', 'zone'}): 0。就是这样问题出在哪里.. :(
  • @Jeeva 请检查您的output 变量在哪里更改为output.keys()。这就是错误。不知何故,您的输出变量在传递给函数之前发生了变化。
  • 更新了完整代码..请检查
  • @Jeeva traceback 仍然缺少您在控制台中获得的内容。请复制过去您在控制台中获得的内容而不进行编辑。

标签: python python-3.x dictionary


【解决方案1】:

问题是您将dict 对象传递给map。当map 迭代output 中的项目时,它会这样做:

for key in output:  # When you iterate over a dictionary, you just get the keys.
    func2(key)

因此,每次调用 func2 时,output 中包含的所有内容都是字典中的一个键(frozenset)。

根据您上面的 cmets,您似乎想将整个字典传递给 func2,但如果您这样做,您实际上根本没有并行执行任何操作。我想也许你认为这样做

pool.map(func2, output, chunksize=4)

将导致output 字典被拆分为四个字典,每个块被传递给func2 的一个实例。但事实并非如此。相反,字典中的每个键都是单独发送的 func2

chunksize 只是用来告诉pool 有多少output 的元素一次通过进程间通信发送给每个子进程。它仅用于内部目的;无论您使用什么chunksizefunc2 都只会被output 的单个元素调用。

如果你想真正传递字典的块,你需要做这样的事情:

# Break the output dict into 4 lists of (key, value) pairs
items = list(output.items())
chunksize = 4
chunks = [items[i:i + chunksize ] for i in range(0, len(items), chunksize)]
reduced_values= p.map(func2, chunks)

这会将(key, value) 元组的列表从output 字典传递到func2。然后,在func2 中,您可以将列表转回字典:

def reduce(prob,result,output):
    output = dict(item for item in output)  # Convert back to a dict
    print(output)
    ...

【讨论】:

  • 谢谢。我对 chunksize 的理解是错误的,感谢您的澄清。您能否解释一下为什么在 p.map 的任何地方都没有使用“块”?我想我们需要在 reduce_values= p.map( func2,output,chunksize=4) 中使用块代替输出?我得到这个错误 chunks = [items[i:i + chunksize] for i in range(0, len(items), chunksize)] TypeError: 'dict_items' object is not subscriptable
  • @Jeeva 我已经编辑了我的答案来解决这些问题。我应该将chunks 传递给pool.map,而不是output。而在 Python 3 中,dict.items() 不返回列表,而是返回 dict 视图,这不是我们想要的,所以我明确地将其转换为 list
  • 是的。它有效,感谢您的解释,而不仅仅是给出答案。这对学习有很大帮助.. :) 只是好奇,制作列表将比任何其他数据类型占用更多的内存,不是吗?是否可以创建元组或任何其他数据类型而不考虑列表转换?
  • 这给了我这样的列表中的字典集 [{frozenset({'zone', 'rfid'}): 0.35, frozenset({'zone', 'time', 'rfid '}): 1.0}, {frozenset({'zone'}): 0, frozenset({'time'}): 0}] 怎么做成单字典?
  • @Jeeva dict 对象肯定有 update 函数。不过,我确实在上面打错了字。 final_dict = {] 应该是 final_dict = {}
【解决方案2】:

问题是,您正试图在output.keys() 中访问frozenset.keys

setfrozenset 用于执行设置操作,如UNIONINTERSECTION 等。

当您在 frozenset 中传递 arg 时,它会将其转换为 frozenset 对象,并且当您在 reducer you passed output it might have onlyoutput 中传递 output 时,frozenset 没有您试图访问 @for k in output.keys(): 的方法 for k in output.keys(): .keyslike[frozenset({...}), frozenset({...})], when you try to accessoutput.keys()meansfrozenset({...}).keys`它给出错误。

【讨论】:

  • {'rfid', 'zone'} 不是字典文字。这是一个集合文字。
  • 是的。我没有通过frozenset。我正在将具有“frozenset 作为键”的字典作为可迭代参数传递给 p.map。
  • 怎么会是frozenset.keys??正如您在上面看到的,我将“输出”——字典作为迭代器传递。如果你能看到数据,输出有这个 => {frozenset({'rfid', 'zone'}): 0, freezeset({'zone'}): 0, frozenset({'zone', 'time'} ): 0}
  • @Lafada 是的,我能理解。但我正在使用 output.keys() 因为输出是我的字典,这是我传递给该函数的字典。我没有使用frozenset.keys,我想知道为什么我只得到这个frozenset({'rfid','zone'}),而不是frozenset({'rfid','zone'}):函数内部的0跨度>
  • 不,我试图从减速器功能打印输出,我得到了整个字典,而不仅仅是键..
猜你喜欢
  • 1970-01-01
  • 2021-08-25
  • 2021-04-15
  • 2011-07-31
  • 2021-10-28
  • 2015-09-21
  • 2013-08-21
  • 2016-01-17
  • 2013-12-03
相关资源
最近更新 更多