Перебрать словарь и вернуть все ключи и значения в обновленной форме, используя модуль многопроцессорности в python.

Изначально у меня есть структура данных, такая как 'motif':

мотив = { '1S-2C,2C-2C' :[ [[1,2],[2,2]], [[3,5],[5,5]], [ [4,6],[6,6]] ],'1S-1S,1S-2C': [[[1,1],[1,2]], [[3,3],[3,5 ]] ]}*

Я хотел бы создать подпроцесс для каждого ключа и передать его в некоторую функцию с именем 'extension()'. Обновление каждого элемента выполняется в 'modify()'.

Проблема с приведенным ниже фрагментом: я получаю вывод, подобный этому 'returnMotif': {'1S-2C,2C-2C,3E-3E':[[[1, 2], [2 , 2], [0, 0]], [[3, 5], [5, 5], [0, 0]], [[4, 6], [6, 6], [0, 0]] ],'1S-1S,1S-2C,3O-3O': [[[1,1],[1,2],[0,0]], [[3,3],[3,5], [0,0]] ]} .т.е. они точно падают туда же откуда звонили не глядя на клавиши. Но я хочу, чтобы «returnMotif» выглядел так:

returnMotif = { '1S-2C,2C-2C,3E-3E' : [[[1,2],[2,2],[0,0]], [[4,6 ],[6,6],[0,0]] ], '1S-1S,2C-2C,3O-3O' : [[[3,5],[5,5],[0,0]] ], '1S-1S,1S-2C,3E-3E' : [[[1,1],[1,2],[0,0]]], '1S-1S,1S-2C,3O-3O ' : [ [[3,3],[3,5],[0,0]] ]} Итак, как я могу перебрать словарь 'motif' с помощью многопроцессорного модуля и получить все обновленные элементы в 'returnMotif' в main()?

У меня есть такой патч: Может ли кто-нибудь внести какие-либо изменения по этому поводу?

from multiprocessing import Pool,Manager
from collections import defaultdict

def modify(x,i):
    #print i[1][1]
    if i[1][1] % 2 == 0:    
        return x+',3E-3E' #last element is even
    else:
        return x+',3O-3O'# last element is odd

def extension(x):  # Function that is called during multiprocessing.
    # do some function on each element like  [[1,2],[2,2]],[[3,5],5,5]], [[1,1],[1,2]], [[3,3],[3,5]], [[4,6],[6,6]]. Let it be the function 'modify()'
    #print x # should have the key
    #print motif[x] # clearly has the value
    allTemps=[]
    for i in motif[x]:
        #print i
        (newX) = modify(x, i)
        i.append([0,0])
        allTemps.append(i)
    return (newX,allTemps)

if __name__ == "__main__":
    # Dictionary with list of list of parameters:

    motif={'1S-2C,2C-2C':[ [[1,2],[2,2]], [[3,5],[5,5]], [[4,6],[6,6]] ]}

    p = Pool(4)  # Setting up the number of CPU's to use.

    returnMotif = dict( p.map( extension , motif.keys() ) )

    p.close()
    p.join()

# when I return the modified keys and values, they exactly fall in the same place from where they called without looking at the keys ie, [[1,2],[2,2]], [[3,5],[5,5]], [[4,6],[6,6]] these 3 elements have the same key '1S-2C,2C-2C'. But in the modified key-value pairs, only two of them have same key and the third one is having a different key. ie, [[1,2],[2,2],[0,0]] ,  [[4,6],[6,6],[0,0]] these two elements have a key of  '1S-2C,2C-2C,3E-3E' and  [[3,5],[5,5],[0,0]] has a key of  '1S-2C,2C-2C,3O-3O'. But it's coming like this: ** returnMotif ** 1S-2C,2C-2C,3E-3E     [[[1, 2], [2, 2], [0, 0]], [[3, 5], [5, 5], [0, 0]], [[4, 6], [6, 6], [0, 0]]] 
#I want it to be split into two key-value pair like format below :{'1S-2C,2C-2C,3E-3E':[[[1, 2], [2, 2], [0, 0]],  [[4, 6], [6, 6], [0, 0]]] ,'1S-2C,2C-2C,3O-3O':[ [[3, 5], [5, 5], [0, 0]] ]}



print "**  Return Motifs:\n"
for i in returnMotif:
    print i,"\t",returnMotif[i],"\n"

person ANJALY    schedule 24.03.2017    source источник


Ответы (1)


Вот быстрый Proof-o'-Concept, который я провел:

from multiprocessing import Pool

m = {
  'a': [ 1,2 ] ,
  'b': [ 3,4 ] ,
  'c': [ 5,6 ] ,
}

def f(x):
    return (x,m[x][0] + m[x][1])

if __name__ == '__main__':
    p = Pool(5)
    print(p.map(f, m.keys() ))

Программа выше (как вы можете видеть, это производная работа от примера, приведенного в 16.6. многопроцессорная страница ) добавит числа в простые списки в моем примерном словаре m, чтобы получить следующий результат:

[('a', 3), ('c', 11), ('b', 7)]

В общем, я предполагаю, что если вы упростите использование многопроцессорного модуля, чтобы использовать карту вместо apply_async, вам будет легче.

Соединяя точки, вот фрагмент:

from multiprocessing import Pool,Manager

def extension(x):  # Function that is called during multiprocessing.
    # do some function on each element like  [[1,2],[2,2]], [[3,5],[5,5]], [[1,1],[1,2]], [[3,3],[3,5]], [[4,6],[6,6]]
    # ** MISTAKE : Not getting elements here for processing along with it's corresponding key **
    #print x,"\t\n"
    #print x # should have the key
    #print motif[x] # clearly has the value
    return (x,motif[x])

if __name__ == "__main__":
    # Dictionary with list of list of parameters:
    motif={'1S-2C,2C-2C':[ [[1,2],[2,2]], [[3,5],[5,5]], [[4,6],[6,6]] ],'1S-1S,1S-2C': [ [[1,1],[1,2]], [[3,3],[3,5]] ] }
    p = Pool(4)  # Setting up the number of CPU's to use.

    returnMotif = dict( p.map( extension , motif.keys() ) )

    p.close()
    p.join()

    print returnMotif

Предостережение: мне не ясно, что доступ только для чтения к мотиву словаря является потокобезопасным. В java-приложении, которое я когда-то написал, HashMap, который я использовал, обновлялся каждый раз, когда его читали, поскольку он поддерживал связанный список для отслеживания наименее недавно использовавшихся.

Хорошо, второе предостережение: код в функции расширения ни в коем случае не должен изменять словарь мотивов. Ключи не должны добавляться или удаляться наверняка.

На основе недавнего комментария ANJALY (25 марта 2017 г.) приведен обновленный фрагмент кода, обеспечивающий желаемое поведение. На самом деле это не имеет ничего общего с асинхронной обработкой, поэтому я оставлю приведенный выше код и опубликую новый фрагмент ниже:

from multiprocessing import Pool,Manager
def modify(x,i):
    i.append([0,0])
    modX = x+',3S-3S'
    #print modX,"\t",i,"\n**\n"
    return (modX,i)

def extension(x):  # Function that is called during multiprocessing.
    # do some function on each element like  [[1,2],[2,2]], [[3,5],5,5]], [[1,1],[1,2]], [[3,3],[3,5]], [[4,6],[6,6]]. Let it be the function 'modify()'
    #print x # should have the key
    #print motif[x] # clearly has the value
    alltemps=[]
    for  i in motif[x]:
        (newX,temp) = modify(x,i)
        alltemps.append(temp)
    return (newX,alltemps)
if __name__ == "__main__":
    # Dictionary with list of list of parameters:

    motif={'1S-2C,2C-2C':[ [[1,2],[2,2]], [[3,5],[5,5]], [[4,6],[6,6]] ],'1S-1S,1S-2C': [ [[1,1],[1,2]], [[3,3],[3,5]] ] }
    p = Pool(4)  # Setting up the number of CPU's to use.

    returnMotif = dict( p.map( extension , motif.keys() ) )

    p.close()
    p.join()
print returnMotif

В приведенном выше коде я добавил локальную переменную (очень важно, чтобы переменная была локальной в многопроцессорной среде) для сбора результатов. Я также переместил оператор return из цикла (я превзошел его).

person Mark    schedule 24.03.2017
comment
Фрагмент, приведенный выше, правильно принимает ключи и значения. Но только последний элемент каждого ключа модифицируется и вводится в «returnMotif». Но я хочу, чтобы все элементы обновлялись, а «returnMotif» был похож на «returnMotif» = {'1S-2C, 2C-2C, 3S-3S' :[[[[1,2],[2,2],[0,0]], [[3,5],[5,5],[0,0]], [[4,6],[ 6,6],[0,0]] ],'1S-1S,1S-2C,3S-3S': [[[1,1],[1,2],[0,0]], [[ 3,3],[3,5],[0,0]] ] } - person ANJALY; 25.03.2017
comment
если возвращаемые значения не имеют одного и того же ключа, как я могу обновить returnMotif новой парой ключ-значение. [2, 2], [0, 0]], [[3, 5], [5, 5], [0, 0]], [[4, 6], [6, 6], [0, 0 ]]]. Я хочу, чтобы он был разделен на две пары ключ-значение, как показано ниже: «1S-2C, 2C-2C, 3E-3E»: {[[[1, 2], [2, 2], [0, 0] ], [[4, 6], [6, 6], [0, 0]]] } '1S-2C,2C-2C,3O-3O': { [[3, 5], [5, 5] , [0, 0]] } - person ANJALY; 31.03.2017