Explicación de hilos de demonio

237

En la documentación de Python dice:

Un hilo se puede marcar como un "hilo de demonio". La importancia de este indicador es que todo el programa Python se cierra cuando solo quedan hilos de daemon. El valor inicial se hereda del hilo de creación.

¿Alguien tiene una explicación más clara de lo que eso significa o un ejemplo práctico que muestra dónde establecería los hilos daemonic?

Aclárelo para mí: entonces, ¿la única situación en la que no establecería subprocesos daemonices cuando desea que continúen ejecutándose después de que se cierre el subproceso principal?

Corey Goldberg
fuente

Respuestas:

448

Algunos subprocesos realizan tareas en segundo plano, como el envío de paquetes keepalive, o la recolección periódica de basura, o lo que sea. Estos solo son útiles cuando el programa principal se está ejecutando, y está bien matarlos una vez que los otros hilos, que no son demonios, hayan salido.

Sin hilos de daemon, tendrías que hacer un seguimiento de ellos y decirles que salgan, antes de que tu programa se pueda cerrar por completo. Al configurarlos como hilos de demonio, puede dejarlos correr y olvidarse de ellos, y cuando su programa se cierra, cualquier hilo de demonio se elimina automáticamente.

Chris Jester-Young
fuente
1
Entonces, si tengo un subproceso secundario que está realizando una operación de escritura de archivos que está configurada en no demonio, ¿eso significa que tengo que hacer que salga explícitamente?
Ciasto piekarz
8
@san ¿Qué hace tu hilo de escritor cuando termina de escribir? ¿Solo regresa? Si es así, eso es suficiente. Los hilos de demonio son generalmente para cosas que se ejecutan en un bucle y no salen por sí solas.
Chris Jester-Young
No hace nada, ni regresa, su único propósito es realizar la operación de escritura de archivos
Ciasto piekarz
2
@san Si se cae de la parte inferior de la función de subproceso, regresa implícitamente.
Chris Jester-Young
Regresa Noneen ese caso, pero no importa, el valor de retorno no se usa.
Chris Jester-Young
30

Digamos que estás haciendo algún tipo de widget de tablero. Como parte de esto, desea que muestre el recuento de mensajes no leídos en su casilla de correo electrónico. Entonces haces un pequeño hilo que:

  1. Conéctese al servidor de correo y pregunte cuántos mensajes no leídos tiene.
  2. Señale la GUI con el recuento actualizado.
  3. Duerme un rato.

Cuando se inicia su widget, crearía este hilo, lo designaría como un demonio y lo iniciaría. Debido a que es un demonio, no tienes que pensarlo; cuando su widget salga, el hilo se detendrá automáticamente.

John Fouhy
fuente
18

Otros carteles dieron algunos ejemplos de situaciones en las que usaría hilos de daemon. Mi recomendación, sin embargo, es nunca usarlos.

No es porque no sean útiles, sino porque hay algunos efectos secundarios negativos que puede experimentar si los usa. Los subprocesos de Daemon aún pueden ejecutarse después de que el tiempo de ejecución de Python comience a derribar cosas en el subproceso principal, lo que causa algunas excepciones bastante extrañas.

Más información aquí:

https://joeshaw.org/python-daemon-threads-considered-harmful/

https://mail.python.org/pipermail/python-list/2005-February/343697.html

Estrictamente hablando, nunca los necesita, solo facilita la implementación en algunos casos.

Joe Shaw
fuente
¿Todavía este problema con Python 3? No hay información clara sobre estas "extrañas excepciones" en la documentación.
kheraud
55
De la publicación del blog de Joe: "Actualización de junio de 2015: este es el error de Python 1856. Se corrigió en Python 3.2.1 y 3.3, pero la solución nunca se hizo retroceder a 2.x. (Un intento de retroceder a la rama 2.7 causó otro error y fue abandonado.) Los hilos de Daemon pueden estar bien en Python> = 3.2.1, pero definitivamente no están en versiones anteriores ".
clacke
Me gustaría compartir aquí mi experiencia: tuve una función generada como Thread varias veces. Dentro de él, tuve una instancia de Python loggingy esperaba que, después de terminar el hilo, todos los objetos (descriptores de archivo para cada hilo / función), serían destruidos. Al final de mi programa, vi muchos resultados como IOError: [Errno 24] Too many open files:. Con lsof -p pid_of_program, descubrí que los FD estaban abiertos, incluso los Thread / Functions han terminado su trabajo. ¿Solución alterna? Eliminando el controlador de registro al final de la función. Así daemonicHilos, son poco fiables ...
ivanleoncz
17

Una forma más sencilla de pensarlo, tal vez: cuando regrese main, su proceso no se cerrará si todavía hay subprocesos no daemon en ejecución.

Un pequeño consejo: el apagado limpio es fácil de equivocarse cuando hay hilos y sincronización involucrados; si puede evitarlo, hágalo. Use hilos de demonio siempre que sea posible.

Jonathan
fuente
13

Chris ya explicó qué son los hilos de daemon, así que hablemos sobre el uso práctico. Muchas implementaciones de grupos de subprocesos usan subprocesos de daemon para trabajadores de tareas. Los trabajadores son hilos que ejecutan tareas desde la cola de tareas.

El trabajador debe seguir esperando las tareas en la cola de tareas de forma indefinida, ya que no saben cuándo aparecerá una nueva tarea. El subproceso que asigna tareas (por ejemplo, el subproceso principal) solo sabe cuándo finalizan las tareas. El subproceso principal espera en la cola de tareas para quedar vacío y luego sale. Si los trabajadores son hilos de usuario, es decir, no demonios, el programa no terminará. Seguirá esperando a estos trabajadores que se ejecutan indefinidamente, a pesar de que los trabajadores no están haciendo nada útil. Marque los hilos de demonio de los trabajadores, y el hilo principal se encargará de matarlos tan pronto como termine de manejar las tareas.

Amit
fuente
44
¡Ten cuidado con eso! Si un programa envía una tarea importante (por ejemplo, actualizar algún archivo "en segundo plano") a una cola de tareas de daemon, entonces existe el riesgo de que el programa pueda terminar antes de realizar la tarea, o peor aún, en medio de la actualización de ese archivo.
Solomon Slow
10

Citando a Chris: "... cuando su programa se cierra, todos los hilos de demonio se eliminan automáticamente". Creo que eso lo resume todo. Debe tener cuidado cuando los use, ya que terminan abruptamente cuando el programa principal se ejecuta hasta su finalización.

Bajo
fuente
4

Cuando su segundo subproceso no es Daemon, el subproceso principal principal de su aplicación no puede salir porque sus criterios de salida también están vinculados a la salida de subprocesos que no son Daemon. Los hilos no se pueden matar por la fuerza en python, por lo tanto, su aplicación tendrá que esperar realmente a que salgan los hilos que no son Daemon. Si este comportamiento no es lo que desea, configure su segundo hilo como daemon para que no impida que su aplicación salga.

truthadjustr
fuente