Python: Olvídate de los hilos y usa "futures"
Soy un usuario masivo de hilos a la hora de programar en Python. Mi gestión de la complejidad y las condiciones de carrera se basa en ser cuidadoso y, cuando el problema lo permite, usar colas u otros mecanismos de sincronización y comunicación. Podría decirse que uso un modelo de actores en Python.
Con cuidado y experiencia me las apaño bastante bien. Es raro que tenga problemas.
Python 3.2 introdujo el concepto de Futures, un tipo de paralelismo que abstrae el uso de hilos o multiprocesamiento. En mi caso personal lo que más me interesa es la facilidad para seguir la pista a los diferentes hilos que lanzo, más concretamente para detectar de forma sencilla cuándo terminan correctamente o cuándo mueren debido a una excepción.
Antes de los futures, mis hilos estaban contenidos en algo similar a:
try: [ El cuerpo de mi hilo] except Exception as exc: [ Notifica de alguna manera mágica que el hilo ha fallado ] raise [ Notifica de alguna manera mágica que el hilo ha terminado correctamente ]
Además, el hilo supervisor tiene que gestionar esas notificaciones de alguna manera.
El resultado no es complicado, pero cansa repetir todo esto en cada proyecto. Repetirte indica claramente que hay una carencia a cubrir.
La cosa se ha simplificado mucho con la introducción de los Futures en Python 3.2. El hilo principal solo necesita hacer lo siguiente:
fut = executor.submit(funcion, params) ... resultado = fut.result()
En resultado tendremos el resultado de la función si terminó con normalidad, o se levantará una excepción en ese punto con los detalles del fallo en la ejecución de la función.
fut.result() es bloqueante, pero podemos emplear cosas como concurrent.futures.as_completed() para procesar Futures a medida que van terminando o concurrent.futures.wait() para esperar a que terminen todos. Entre otras cosas.
Además de esta facilidad, los Futures nos permiten indicar qué nivel de concurrencia queremos o si queremos utilizar hilos o multiprocesamiento.
Léete la documentación con calma y olvídate de usar hilos directamente.
Un detalle interesante que debes recordar, no obstante, es que el programa no terminará hasta que todos los Futures en curso completen su ejecución. Esto lo explico mejor en Que tus "futures" de larga duración no impidan que tu programa Python termine.