2010-10-04 26 views
11

Lors de l'utilisation du module de thread et de la classe Thread(), SIGINT (Ctrl + C dans la console) n'a pas pu être intercepté.Comment puis-je attraper SIGINT dans le programme de threading python?

Pourquoi et que puis-je faire?

programme de test simple:

#!/usr/bin/env python 

import threading 

def test(suffix): 
    while True: 
     print "test", suffix 

def main(): 
    for i in (1, 2, 3, 4, 5): 
     threading.Thread(target=test, args=(i,)).start() 

if __name__ == "__main__": 
    main() 

Essayez de frapper Ctrl-C - rien ne se passe.

Répondre

8

Les fils et les signaux ne se mélangent pas. En Python, c'est encore plus vrai à l'extérieur qu'à l'extérieur: les signaux ne sont jamais transmis qu'à un seul thread (le thread principal); les autres threads ne recevront pas le message. Vous ne pouvez rien faire pour interrompre les threads autres que le thread principal. Ils sont hors de votre contrôle. La seule chose que vous pouvez faire ici est d'introduire un canal de communication entre le thread principal et les threads que vous démarrez, en utilisant le module queue. Vous pouvez alors envoyer un message au thread et le faire se terminer (ou faire tout ce que vous voulez) quand il voit le message.

Alternativement, et c'est souvent une très bonne alternative, est de ne pas utiliser de threads. Cependant, ce que vous devez utiliser dépend grandement de ce que vous essayez d'accomplir.

+3

Le fil principal ne reçoit pas SIGINT non plus. Sinon, je pourrais juste l'attraper et appeler sys.exit (0). –

+0

Il semble que j'ai tort. Le thread principal reçoit SIGINT. Je vous remercie! –

+0

Mais je ne comprends pas pourquoi sys.exit (0) ne fonctionne pas dans le gestionnaire de signal. –

-1

Fondamentalement, vous pouvez vérifier si le parent a émis un signal en lisant une file d'attente pendant le travail. Si le parent reçoit un SIGINT alors il émet un signal à travers la file (dans ce cas n'importe quoi) et les enfants terminent leur travail et sortent ...

def fun(arg1, thread_no, queue): 
    while True: 
    WpORK... 
    if queue.empty() is False or errors == 0: 
    print('thread ', thread_no, ' exiting...') 
    with open('output_%i' % thread_no, 'w') as f: 
     for line in lines: f.write(line) 
    exit() 

threads = [] 
for i, item in enumerate(items): 
threads.append(dict()) 
q = queue.Queue() 
threads[i]['queue'] = q 
threads[i]['thread'] = threading.Thread(target=fun, args=(arg1, i, q)) 
threads[i]['thread'].start() 
try: 
time.sleep(10000) 
except: 
for thread in threads: 
    thread['queue'].put('TERMINATING') 
+0

S'il vous plaît envisager de décrire pourquoi ce code fonctionne. Le dumping de code est généralement déconseillé sur StackOverflow. – rayryeng