2012-03-28 11 views
10

Próbuję wywołać funkcję na wielu procesach. Oczywistym rozwiązaniem jest moduł Pythona multiprocessing. Problem polega na tym, że funkcja ma skutki uboczne. Tworzy plik tymczasowy i rejestruje ten plik, który ma zostać usunięty przy wyjściu, korzystając z atexit.register i listy globalnej. Poniższe informacje powinny pokazać problem (w innym kontekście).Pythonowa mapa równoległa (multiprocessing.Pool.map) z globalnymi danymi

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. 

Czy istnieje sposób na zaktualizowanie globalnych danych?

Należy zauważyć, że jeśli wypróbujesz powyższy skrypt, prawdopodobnie nie powinieneś wypróbować go z interaktywnego interpretera, ponieważ multiprocessing wymaga, aby moduł __main__ mógł być importowany przez procesy potomne.

UPDATE

Dodano global kluczowe w func nie pomaga - np

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

Odpowiedz

18

trzeba, że ​​lista (glob_data) być poparte pamięci współdzielonej, Manager Multiprocessing daje Ci tylko, że:

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. 

jakiegoś tle (wyszukiwanie Manager):

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

+1

Pozdrawiam, działa to doskonale dla mnie. Powinienem tu wspomnieć, że działa, ponieważ obiekty, które dołączam do glob_data są niezmienne (w tym przykładzie ciągi w mojej aplikacji). Jeśli obiekty, które są spakowane na liście, są zmienne, należy zachować ostrożność, aby ponownie je dodać do listy, jeśli zostaną zmienione. – mgilson

+0

do usług :) –

+0

@RafaelFerreira Działa dobrze! ale wyniki nie są spójne, tak jak w moim przypadku .. używam manage.dict(), wartości zmieniają się za każdym razem, gdy uruchamiam mój kod. Widzę, że blokada powinna być zastosowana, ale nie jestem pewna. –

1

Czy func powrócić krotki z wynikami chcesz z przetwarzaniem i rzecz, którą chcesz dołączyć do glob_data. Następnie, po ukończeniu p.map, możesz wyodrębnić wyniki z pierwszych elementów z zwróconych krotek i możesz zbudować glob_data z drugich elementów.

+0

Tak , Myślałem o tym ... Mój przypadek użycia jest nieco bardziej skomplikowany. Pliki tymczasowe, które chcę usunąć, są ukryte głęboko w klasach, a ponieważ są to tylko pliki tymczasowe, wolę zachować je i ich nazwy jako prywatną część klasy API (szczegóły implementacji) ... – mgilson