2010-10-04 14 views
11

Al usar el módulo de subprocesamiento y la clase Thread(), SIGINT (Ctrl + C en la consola) no podría ser capturado.¿Cómo puedo detectar SIGINT en el programa de threading python?

¿Por qué y qué puedo hacer?

programa de prueba 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() 

Prueba presionando Ctrl-C - no pasa nada.

Respuesta

8

Los hilos y las señales no se mezclan. En Python, esto es aún más cierto que en el exterior: las señales solo se envían a un hilo (el hilo principal); otros hilos no recibirán el mensaje. No hay nada que puedas hacer para interrumpir los hilos que no sean el hilo principal. Están fuera de tu control.

Lo único que puede hacer aquí es introducir un canal de comunicación entre el hilo principal y los hilos que inicie, utilizando el módulo queue. Luego puede enviar un mensaje al hilo y hacer que termine (o hacer lo que desee) cuando vea el mensaje.

Alternativamente, y a menudo es una muy buena alternativa, es no usar hilos. Sin embargo, qué usar en su lugar depende en gran medida de lo que intente lograr.

+3

El hilo principal tampoco recibe SIGINT. De lo contrario, podría atraparlo y llamar a sys.exit (0). –

+0

Parece que estoy equivocado. El hilo principal no recibe SIGINT. ¡Gracias! –

+0

Pero no entiendo por qué sys.exit (0) no funciona en el controlador de señal. –

-1

Básicamente puede verificar si el padre emitió una señal leyendo una cola durante el trabajo. Si el padre recibe un SIGINT, emite una señal en la cola (en este caso cualquier cosa) y los niños finalizan su trabajo y salen ...

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

Considere describir por qué funciona este código. En general, se desaconseja el dumping de códigos en StackOverflow. – rayryeng

Cuestiones relacionadas