2012-03-28 2 views
10

Я пытаюсь вызвать функцию для нескольких процессов. Очевидным решением является модуль multiprocessing python. Проблема в том, что функция имеет побочные эффекты. Он создает временный файл и регистрирует этот файл для удаления при выходе с использованием atexit.register и глобального списка. Следующее должно продемонстрировать проблему (в другом контексте).Параллельная карта python (multiprocessing.Pool.map) с глобальными данными

import multiprocessing as multi 

glob_data=[] 
def func(a): 
    glob_data.append(a) 

map(func,range(10)) 
print glob_data #[0,1,2,3,4 ... , 9] Good. 

p=multi.Pool(processes=8) 
p.map(func,range(80)) 

print glob_data #[0,1,2,3,4, ... , 9] Bad, glob_data wasn't updated. 

Есть ли способ обновить глобальные данные?

Обратите внимание, что если вы попробуете приведенный выше скрипт, вам, вероятно, не следует пытаться использовать его из интерактивного интерпретатора, поскольку multiprocessing требует, чтобы модуль __main__ был импортирован дочерними процессами.

UPDATE

Добавлена ​​global ключевое слово в FUNC не помогает - например:

def func(a): #Still doesn't work. 
    global glob_data 
    glob_data.append(a) 

ответ

18

Вам нужен этот список (glob_data) быть подкреплено совместно используемой памятью, менеджер MultiProcessing дает вам только что:

import multiprocessing as multi 
from multiprocessing import Manager 

manager = Manager() 

glob_data= manager.list([]) 

def func(a): 
    glob_data.append(a) 

map(func,range(10)) 
print glob_data #[0,1,2,3,4 ... , 9] Good. 

p=multi.Pool(processes=8) 
p.map(func,range(80)) 

print glob_data # Super Good. 

Для некоторого фона (поиск менеджера):

http://docs.python.org/library/multiprocessing.html

+1

Привет, это отлично работает для меня. Здесь я должен упомянуть, что он работает, потому что объекты, которые я добавляю к glob_data, неизменяемы (ints в примере, строки в моем фактическом приложении). Если они упаковывают объекты в список, они изменяемы, тогда необходимо позаботиться о том, чтобы их добавить в список, если они были изменены. – mgilson

+0

к вашим услугам :) –

+0

@ RafaelFerreira Хорошо работает! но результаты не согласуются, как в моем случае .. Я использую manager.dict(), значения меняются каждый раз, когда я запускаю свой код. Я вижу, что блокировка должна применяться, но не уверен. –

1

У FUNC возвращает кортеж результатов вы хотите от обработки и вещь, которую вы хотите добавить к glob_data. Затем, когда p.map завершен, вы можете извлечь результаты из первых элементов в возвращаемых кортежах, и вы можете построить glob_data из вторых элементов.

+0

Да , Я подумал об этом ... Мой прецедент немного сложнее, чем это. Временные файлы, которые я хочу удалить, скрыты глубоко внутри классов, и поскольку они являются только временными файлами, я предпочитаю хранить их и их имена в качестве частной части API класса (подробности реализации) ... – mgilson

Смежные вопросы