Creo que es mejor llamar a join()
en tus hilos cuando esperas que mueran. Me he tomado la libertad de hacer que el cambio de sus bucles finalice (también puede agregar cualquier necesidad de limpieza que se requiera allí). La variable die
se comprueba en cada pasada y cuando es True
, el programa sale.
import threading
import time
class MyThread (threading.Thread):
die = False
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run (self):
while not self.die:
time.sleep(1)
print (self.name)
def join(self):
self.die = True
super().join()
if __name__ == '__main__':
f = MyThread('first')
f.start()
s = MyThread('second')
s.start()
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
f.join()
s.join()
KeyboardInterrupt y las señales solo son vistas por el proceso (es decir, el hilo principal) ... Eche un vistazo a Ctrl-c, es decir, KeyboardInterrupt para matar hilos en python
Ctrl +C finaliza el subproceso principal, pero debido a que sus subprocesos no están en modo daemon, siguen ejecutándose y eso mantiene vivo el proceso. Podemos convertirlos en demonios:
f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()
Pero luego hay otro problema:una vez que el hilo principal ha iniciado sus hilos, no hay nada más que hacer. Entonces sale, y los hilos se destruyen instantáneamente. Así que mantengamos vivo el hilo principal:
import time
while True:
time.sleep(1)
Ahora mantendrá la impresión 'primero' y 'segundo' hasta que presione Ctrl +C .
Editar: como han señalado los comentaristas, es posible que los subprocesos del daemon no tengan la oportunidad de limpiar cosas como archivos temporales. Si lo necesita, tome el KeyboardInterrupt
en el subproceso principal y hacer que coordine la limpieza y el apagado. Pero en muchos casos, dejar que los subprocesos de daemon mueran repentinamente probablemente sea lo suficientemente bueno.
Una versión mejorada de la respuesta de @Thomas K:
- Definir una función de asistente
is_any_thread_alive()
de acuerdo con esta esencia, que puede terminar elmain()
automáticamente.
Códigos de ejemplo:
import threading
def job1():
...
def job2():
...
def is_any_thread_alive(threads):
return True in [t.is_alive() for t in threads]
if __name__ == "__main__":
...
t1 = threading.Thread(target=job1,daemon=True)
t2 = threading.Thread(target=job2,daemon=True)
t1.start()
t2.start()
while is_any_thread_alive([t1,t2]):
time.sleep(0)