Tengo un módulo de Python que usa multiprocessing
. Estoy ejecutando este módulo desde otro script con runpy
. Sin embargo, esto da como resultado (1) que el módulo ejecute dos veces y (2) los trabajos multiprocessing
nunca finalizan (el script simplemente se cuelga).
En mi ejemplo de trabajo mínimo, tengo un script runpy_test.py :
import runpy
runpy.run_module('module_test')
Y un directorio module_test que contiene un __init__.py vacío y un __main__.py :
from multiprocessing import Pool
print 'start'
def f(x):
return x*x
pool = Pool()
result = pool.map(f, [1,2,3])
print 'done'
Cuando ejecuto runpy_test.py , obtengo:
start
start
Y el guión se cuelga.
Si elimino la llamada pool.map
(o si ejecuto __main__.py directamente, incluida la llamada pool.map
), obtengo:
start
done
Estoy ejecutando esto en Scientific Linux 7.6 en Python 2.7.5.
3 respuestas
Reescribe tu __main__.py
así:
from multiprocessing import Pool
from .implementation import f
print 'start'
pool = Pool()
result = pool.map(f, [1,2,3])
print 'done'
Y luego escriba un implementation.py
(puede llamarlo como quiera) en el que se define su función:
def f(x):
return x*x
De lo contrario, tendrá el mismo problema con la mayoría de las interfaces en el multiprocesamiento, e independientemente del uso de runpy. Como explicó @Weeble, cuando Pool.map
intenta cargar la función f
en cada subproceso, importará <your_package>.__main__
donde se define su función, pero ya que tiene un código ejecutable a nivel de módulo en __main__
el subproceso lo volverá a ejecutar.
Aparte de esta razón técnica, este también es un mejor diseño en términos de separación de preocupaciones y pruebas. Ahora puede importar y llamar fácilmente (incluso con fines de prueba) la función f
sin ejecutarla en paralelo.
Aunque no es la forma "correcta" de hacerlo, una solución que terminó funcionando para mí fue usar _run_module_as_main
de runpy en lugar de run_module
. Esto era ideal para mí ya que estaba trabajando con el código de otra persona y requería la menor cantidad de cambios.
Intente definir su función f
en un módulo separado. Debe ser serializado para pasar a los procesos del grupo, y luego esos procesos deben volver a crearlo, importando el módulo en el que se encuentra. Sin embargo, el archivo __main__.py
en el que se encuentra no es un módulo, o al por lo menos, no se porta bien. Intentar importarlo daría como resultado la creación de otro Pool y otra invocación del mapa, lo que parece una receta para el desastre.
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.