Je teste Python threading avec le script suivant:
import threading
class FirstThread (threading.Thread):
def run (self):
while True:
print 'first'
class SecondThread (threading.Thread):
def run (self):
while True:
print 'second'
FirstThread().start()
SecondThread().start()
Cela tourne dans Python 2.7 sur Kubuntu 11.10. Ctrl+C ne va pas le tuer. J'ai également essayé d'ajouter un gestionnaire pour les signaux du système, mais cela n'a pas aidé:
import signal
import sys
def signal_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
Pour tuer le processus, je le tue par PID après avoir envoyé le programme à l’arrière-plan avec Ctrl+Z, qui n'est pas ignoré. Pourquoi est-ce Ctrl+C être ignoré de manière persistante? Comment puis-je résoudre ça?
Ctrl+C termine le thread principal, mais comme vos threads ne sont pas en mode démon, ils continuent à fonctionner, ce qui maintient le processus actif. Nous pouvons leur faire des démons:
f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()
Mais il y a un autre problème: une fois que le thread principal a démarré vos threads, il ne reste plus rien à faire. Donc, ça sort, et les fils sont détruits instantanément. Alors gardons le fil conducteur en vie:
import time
while True:
time.sleep(1)
Maintenant, il restera imprimé en premier et en second jusqu'à ce que vous appuyiez sur Ctrl+C.
Edit: Comme l'ont souligné les commentateurs, les threads de démon peuvent ne pas avoir l'occasion de nettoyer des éléments tels que des fichiers temporaires. Si vous en avez besoin, récupérez le KeyboardInterrupt
sur le thread principal et coordonnez le nettoyage et l'arrêt. Mais dans de nombreux cas, laisser les threads démon mourir soudainement est probablement suffisant.
KeyboardInterrupt et les signaux ne sont vus que par le processus (le thread principal) ... Regardez Ctrl-c i.e. KeyboardInterrupt pour tuer les threads en python
Je pense qu'il est préférable d'appeler join () sur vos threads lorsque vous vous attendez à ce qu'ils meurent. J'ai pris un peu de liberté avec votre code pour terminer les boucles (vous pouvez également ajouter tout ce dont vous avez besoin de nettoyage). La variable die est vérifiée pour la vérité à chaque passage et lorsqu'il est Vrai, le programme se termine.
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 __== '__main__':
f = MyThread('first')
f.start()
s = MyThread('second')
s.start()
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
f.join()
s.join()