¿Sería posible crear un grupo de Python que no sea demoníaco? Quiero que un grupo pueda llamar a una función que tenga otro grupo dentro.
Quiero esto porque los procesos deamon no pueden crear procesos. Específicamente, causará el error:
AssertionError: daemonic processes are not allowed to have children
Por ejemplo, considere el escenario donde function_atiene una piscina que se ejecuta y function_bque tiene una piscina que se ejecuta function_c. Esta cadena de funciones fallará porque function_bse está ejecutando en un proceso demonio y los procesos demonio no pueden crear procesos.

I want a pool to be able to call a function that has another pool insidey cómo eso interfiere con el hecho de que los trabajadores están demonizados.AssertionError: daemonic processes are not allowed to have childrenRespuestas:
La
multiprocessing.pool.Poolclase crea los procesos de trabajo en su__init__método, los convierte en demoníacos y los inicia, y no es posible restablecer sudaemonatributoFalseantes de que se inicien (y luego ya no está permitido). Pero puede crear su propia subclase demultiprocesing.pool.Pool(multiprocessing.Pooles solo una función contenedora) y sustituir su propiamultiprocessing.Processsubclase, que siempre es no demoníaca, para usarla en los procesos de trabajo.Aquí hay un ejemplo completo de cómo hacer esto. Las partes importantes son las dos clases
NoDaemonProcessyMyPoolen la parte superior y para llamarpool.close()ypool.join()en suMyPoolinstancia al final.fuente
multiprocessing.freeze_support()MyPoollugar del predeterminadoPool? En otras palabras, a cambio de la flexibilidad de iniciar procesos secundarios, ¿qué costos debo pagar? (Si no hubiera costos, presumiblemente el estándarPoolhabría utilizado procesos no demoníacos).Poolclase se ha refactorizado ampliamente, porProcesslo que ya no es un atributo simple, sino un método, que devuelve la instancia de proceso que obtiene de un contexto . Intenté sobrescribir este método para devolver unaNoDaemonPoolinstancia, pero esto da como resultado la excepciónAssertionError: daemonic processes are not allowed to have childrencuando se usa el Pool.Tuve la necesidad de emplear un grupo no demoníaco en Python 3.7 y terminé adaptando el código publicado en la respuesta aceptada. A continuación, se muestra el fragmento que crea el grupo no demoníaco:
Como la implementación actual de
multiprocessingse ha refactorizado extensamente para basarse en contextos, debemos proporcionar unaNoDaemonContextclase que tenga nuestroNoDaemonProcessatributo como.MyPoolluego usará ese contexto en lugar del predeterminado.Dicho esto, debo advertir que hay al menos 2 advertencias para este enfoque:
multiprocessingpaquete y, por lo tanto, podría romperse en cualquier momento.multiprocessinges tan difícil usar procesos no demoníacos, muchos de los cuales se explican aquí . El más convincente en mi opinión es:fuente
AttributeError: module 'multiprocessing' has no attribute 'pool'en Python 3.8.0import multiprocessing.poolEl módulo de multiprocesamiento tiene una interfaz agradable para usar grupos con procesos o subprocesos. Dependiendo de su caso de uso actual, podría considerar usar
multiprocessing.pool.ThreadPoolpara su Pool externo, lo que dará como resultado subprocesos (que permiten generar procesos desde adentro) en lugar de procesos.Puede que esté limitado por el GIL, pero en mi caso particular (probé ambos) , el tiempo de inicio de los procesos desde el exterior,
Poolcomo se creó aquí, superó con creces la soluciónThreadPool.Es muy fácil de intercambio
ProcessesdeThreads. Lea más sobre cómo usar unaThreadPoolsolución aquí o aquí .fuente
En algunas versiones de Python estándar reemplazando piscina con la costumbre puede elevar de error:
AssertionError: group argument must be None for now.Aquí encontré una solución que puede ayudar:
fuente
concurrent.futures.ProcessPoolExecutorno tiene esta limitación. Puede tener un grupo de procesos anidado sin ningún problema:El código de demostración anterior se probó con Python 3.8.
Crédito: respuesta por jfs
fuente
multiprocessing.Pooldentro de aProcessPoolExecutor.Pooltambién es posible!El problema que encontré fue al intentar importar globales entre módulos, lo que provocó que la línea ProcessPool () se evaluara varias veces.
globals.py
Luego importe de forma segura desde otra parte de su código
fuente
He visto gente que se enfrenta a este problema utilizando
celeryla bifurcación demultiprocessingllamada billiard (extensiones de grupo de multiprocesamiento), que permite que los procesos demoníacos generen hijos. El recorrido es simplemente reemplazar elmultiprocessingmódulo por:fuente