2010-10-04 15 views
11

Quando si utilizza il modulo di threading e la classe Thread(), non è stato possibile catturare SIGINT (Ctrl + C in console).Come posso catturare SIGINT nel threading del programma python?

Perché e cosa posso fare?

programma di test semplice:

#!/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() 

Prova a colpire Ctrl-C - non succede nulla.

risposta

8

Thread e segnali non si mescolano. In Python questo è ancora più vero che all'esterno: i segnali vengono sempre consegnati a un thread (il thread principale); altri thread non riceveranno il messaggio. Non c'è niente che puoi fare per interrompere i thread oltre al thread principale. Sono fuori dal tuo controllo.

L'unica cosa che puoi fare qui è introdurre un canale di comunicazione tra il thread principale e qualsiasi thread che inizi, usando il modulo queue. È quindi possibile inviare un messaggio al thread e farlo terminare (o fare qualsiasi altra cosa si voglia) quando vede il messaggio.

In alternativa, ed è spesso un'ottima alternativa, non utilizzare thread. Tuttavia, ciò che si usa dipende in gran parte da ciò che stai cercando di ottenere.

+3

thread principale non ricevono SIGINT neanche. Altrimenti potrei semplicemente prenderlo e chiamare sys.exit (0). –

+0

Sembra che io abbia torto. Il thread principale riceve SIGINT. Grazie! –

+0

Ma non capisco perché sys.exit (0) non funzioni nel gestore di segnali. –

-1

Fondamentalmente è possibile verificare se il genitore ha emesso un segnale leggendo una coda durante il lavoro. Se il genitore riceve un SIGINT allora emette un segnale attraverso la coda (in questo caso nulla) ei bambini avvolgere il loro lavoro e uscire ...

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

Si prega di considerare la descrizione del motivo per cui questo codice funziona. Il dumping del codice è solitamente scoraggiato su StackOverflow. – rayryeng

Problemi correlati