2012-03-28 13 views
10

Ich versuche, eine Funktion für mehrere Prozesse aufzurufen. Die offensichtliche Lösung ist Pythons multiprocessing Modul. Das Problem ist, dass die Funktion Nebenwirkungen hat. Es erstellt eine temporäre Datei und registriert die zu löschende Datei beim Beenden unter Verwendung der atexit.register und einer globalen Liste. Das Folgende sollte das Problem demonstrieren (in einem anderen Kontext).Python parallel Karte (multiprocessing.Pool.map) mit globalen Daten

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. 

Gibt es eine Möglichkeit, die globalen Daten aktualisiert zu haben?

Hinweis: Wenn Sie das obige Skript ausprobieren, sollten Sie es wahrscheinlich nicht über den interaktiven Interpreter ausprobieren, da multiprocessing erfordert, dass das Modul __main__ von untergeordneten Prozessen importiert werden kann.

UPDATE

Added die global Schlüsselwort in func hilft nicht - zB:

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

Antwort

18

Sie müssen diese Liste (glob_data) durch Shared-Memory gesichert werden soll, Multi der Manager gibt Ihnen genau das:

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. 

Für einige Hintergrund (für Manager-Suche):

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

+1

Prost, das funktioniert perfekt für mich. Ich sollte hier erwähnen, dass es funktioniert, weil die Objekte, die ich an glob_data anhänge, unveränderlich sind (in dem Beispiel sind es in der tatsächlichen Anwendung Strings). Wenn Objekte, die in die Liste gepackt werden, änderbar sind, muss darauf geachtet werden, dass sie erneut zur Liste hinzugefügt werden, wenn sie geändert werden. – mgilson

+0

zu Ihren Diensten :) –

+0

@RafaelFerreira Funktioniert gut! aber die Ergebnisse sind nicht konsistent, wie in meinem Fall .. bin mit manager.dict(), Werte ändern sich jedes Mal, wenn ich meinen Code ausführen. Ich sehe, dass die Sperre angewendet werden sollte, aber nicht sicher. –

1

Haben func ein Tupel mit den Ergebnissen kehren Sie aus der Verarbeitung möchten, und das, was Sie wollen an glob_data anhängen. Wenn die p.map abgeschlossen ist, können Sie die Ergebnisse aus den ersten Elementen in den zurückgegebenen Tupeln extrahieren, und Sie können glob_data aus den zweiten Elementen erstellen.

+0

Ja Ich dachte darüber nach ... Mein Anwendungsfall ist ein wenig komplizierter. Die temporären Dateien, die ich löschen möchte, sind tief in Klassen vergraben und da sie nur temporäre Dateien sind, bevorzuge ich sie und ihre Namen als privaten Teil der Klassen-API zu halten (Implementierungsdetails) ... – mgilson

Verwandte Themen