2012-03-28 19 views
10

Estoy tratando de invocar una función en múltiples procesos. La solución obvia es el módulo multiprocessing de python. El problema es que la función tiene efectos secundarios. Crea un archivo temporal y registra ese archivo para eliminar al salir usando atexit.register y una lista global. Lo siguiente debería demostrar el problema (en un contexto diferente).python parallel map (multiprocesamiento.Pool.map) con datos globales

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. 

¿Hay alguna manera de tener los datos globales actualizados?

Tenga en cuenta que si prueba el script anterior, probablemente no debería intentarlo con el intérprete interactivo ya que multiprocessing requiere que el módulo __main__ sea importable por procesos secundarios.

ACTUALIZACIÓN

añadido la palabra clave global en func no ayuda - por ejemplo:

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

Respuesta

18

necesita esa lista (glob_data) para ser respaldado por la memoria compartida, Gerente de multiprocesamiento le da precisamente eso:

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. 

Para algunos antecedentes (buscar Manager):

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

+1

Saludos, esto funciona a la perfección para mi. Debo mencionar aquí que funciona porque los objetos que estoy agregando a glob_data son inmutables (como en el ejemplo, cadenas en mi aplicación real). Si los objetos que se empacan en la lista son mutables, se debe tener cuidado de volver a agregarlos a la lista si se modifican. – mgilson

+0

a su servicio :) –

+0

@RafaelFerreira ¡Funciona bien! pero los resultados no son consistentes, como en mi caso ... estoy usando manager.dict(), los valores cambian cada vez que ejecuto mi código. Veo que se debe aplicar el bloqueo pero no estoy seguro. –

1

Tener func devolver una tupla con los resultados que desea de la transformación y lo que desea para agregar a glob_data. Luego, cuando el p.map se haya completado, puedes extraer los resultados de los primeros elementos en las tuplas devueltas y puedes construir glob_data a partir de los segundos elementos.

+0

Sí , Pensé en eso ... Mi caso de uso es un poco más complicado que eso sin embargo. Los archivos temporales que quiero eliminar están ocultos dentro de las clases y, dado que son solo archivos temporales, prefiero conservarlos a ellos y a sus nombres como una parte privada de la API de clase (detalles de implementación) ... – mgilson