También he tenido problemas con esto. Tenía funciones como miembros de datos de una clase, como un ejemplo simplificado:
from multiprocessing import Pool
import itertools
pool = Pool()
class Example(object):
def __init__(self, my_add):
self.f = my_add
def add_lists(self, list1, list2):
# Needed to do something like this (the following line won't work)
return pool.map(self.f,list1,list2)
que necesitaba usar el self.f función en una llamada Pool.map() desde dentro de la misma clase y no lo hice self.f tomar una tupla como argumento. Como esta función estaba incrustada en una clase, no me resultó claro cómo escribir el tipo de envoltorio que sugerían otras respuestas.
Resolví este problema usando un contenedor diferente que toma una tupla/lista, donde el primer elemento es la función, y los elementos restantes son los argumentos para esa función, llamada eval_func_tuple (f_args). Usando esto, la línea problemática puede ser reemplazada por return pool.map (eval_func_tuple, itertools.izip (itertools.repeat (self.f), list1, list2)). Aquí está el código completo:
del archivo: util.py
def add(a, b): return a+b
def eval_func_tuple(f_args):
"""Takes a tuple of a function and args, evaluates and returns result"""
return f_args[0](*f_args[1:])
del archivo: main.py
from multiprocessing import Pool
import itertools
import util
pool = Pool()
class Example(object):
def __init__(self, my_add):
self.f = my_add
def add_lists(self, list1, list2):
# The following line will now work
return pool.map(util.eval_func_tuple,
itertools.izip(itertools.repeat(self.f), list1, list2))
if __name__ == '__main__':
myExample = Example(util.add)
list1 = [1, 2, 3]
list2 = [10, 20, 30]
print myExample.add_lists(list1, list2)
Correr main.py dará [11, 22, 33]. Siéntase libre de mejorar esto, por ejemplo eval_func_tuple también podría ser modificado para tomar argumentos de palabra clave.
En otro aspecto, en otras respuestas, la función "parmap" se puede hacer más eficiente para el caso de más procesos que la cantidad de CPU disponibles. Estoy copiando una versión editada a continuación. Esta es mi primera publicación y no estaba seguro de si debería editar directamente la respuesta original. También cambié el nombre de algunas variables.
from multiprocessing import Process, Pipe
from itertools import izip
def spawn(f):
def fun(pipe,x):
pipe.send(f(x))
pipe.close()
return fun
def parmap(f,X):
pipe=[Pipe() for x in X]
processes=[Process(target=spawn(f),args=(c,x)) for x,(p,c) in izip(X,pipe)]
numProcesses = len(processes)
processNum = 0
outputList = []
while processNum < numProcesses:
endProcessNum = min(processNum+multiprocessing.cpu_count(), numProcesses)
for proc in processes[processNum:endProcessNum]:
proc.start()
for proc in processes[processNum:endProcessNum]:
proc.join()
for proc,c in pipe[processNum:endProcessNum]:
outputList.append(proc.recv())
processNum = endProcessNum
return outputList
if __name__ == '__main__':
print parmap(lambda x:x**x,range(1,5))
"esto como una función de una clase"? ¿Puedes publicar el código que realmente obtiene el error real? Sin el código real, solo podemos adivinar lo que estás haciendo mal. –
@ S.Lott publiqué el código – Mermoz
Como observación general, existen módulos de decapado más potentes que el módulo pickle estándar de Python (como el [picloud] (https://pypi.python.org/pypi/cloud/2.7.2) módulo mencionado en [esta respuesta] (http://stackoverflow.com/a/16626757/2292832)). –