Procesos multiprocesamiento e independencia de Python de niños.

Desde el terminal de Python, ejecuto un comando como el siguiente, para generar un proceso hijo de larga ejecución:

from multiprocessing.process import Process Process(target=LONG_RUNNING_FUNCTION).start() 

Este comando regresa y puedo hacer otras cosas en el terminal de Python, pero todo lo impreso por el niño todavía se imprime en mi sesión de terminal de python.

Cuando salgo de la terminal (ya sea con exit o CTRL + D ), el comando de salida se cuelga. Si presiono CTRL + C durante este locking, el proceso hijo se termina.

Si mato el proceso del terminal python manualmente (a través del comando posix kill ), el proceso hijo queda en su lugar huérfano y continúa ejecutándose con su salida presumiblemente descartada.

Si ejecuto este código con python -c , espera a que termine el hijo, y CTRL + C mata tanto al padre como al hijo.

¿Qué configuraciones de ejecución de python matan a los niños cuando los padres terminan? En particular, si un servidor web python-mod_wsgi-apache genera procesos secundarios y luego se reinicia, ¿se matan los niños?

[Como nota al margen, ¿cuál es la forma correcta de separar los procesos secundarios generados desde el terminal? ¿Hay alguna manera más elegante que la siguiente: hacer deliberadamente un proceso huérfano en python ]

Actualización: los subprocesos de Python generados con multiprocessing.Process por parte de un servidor web que se ejecuta bajo Apache no se cancela cuando se reinicia Apache.

Esto no es una cuestión de cómo estás invocando python; Es una característica del módulo multiprocessing . Cuando importa ese módulo, se agrega un controlador de salida al proceso principal que llama a join() en los objetos de Process de todos los elementos secundarios creados mediante multiprocessing.Process Process antes de permitir que el elemento principal salga. Si va a iniciar procesos secundarios de esta manera, no hay forma, sin hackear los módulos internos, de evitar el comportamiento que le está dando problemas.

Si desea iniciar un proceso que pueda sobrevivir al padre, es probable que tenga un mejor servicio utilizando subprocess.Popen . Si el niño comenzó de esa manera, el padre no intentará unirse al niño antes de salir y en su lugar saldrá inmediatamente, dejando un niño huérfano:

 >>> from subprocess import Popen >>> Popen(["sleep", "100"])  >>> exit() alp:~ $ ps -opid,ppid,command | grep sleep | grep -v grep 37979 1 sleep 100 

¿Hay alguna razón en particular por la que esté utilizando multiprocessing lugar de subprocess ? El primero no está destinado a utilizarse para crear procesos secundarios destinados a sobrevivir al padre; es para crear procesos secundarios para realizar un trabajo que puede ser útilmente paralelizado en las CPU, como una forma de sortear el locking global de intérpretes . (Estoy ignorando las capacidades distribuidas de multiprocessing para los propósitos de esta discusión). Por lo tanto, el multiprocessing se usa normalmente en aquellos casos en los que, si no hubiera un GIL, usarías hilos. (Tenga en cuenta, a este respecto, que la API del módulo de multiprocessing está modelada muy de cerca a la del módulo de threading ).

Para las preguntas específicas al final de su publicación: (1) Nada acerca de python es responsable de matar a los niños cuando se termina el padre. Un hijo del servidor web solo se eliminará si el padre lo mata antes de salir (o si se elimina todo el grupo de proceso). (2) El método al que se vincula parece que intenta replicar la demonización sin conocer los lenguajes estándar para hacerlo. Hay una serie de paquetes para crear procesos de daemon; Deberías usar uno de ellos en su lugar.