2010-10-04 2 views
11

При использовании модуля потоковой передачи и класса Thread() SIGINT (Ctrl + C на консоли) не удалось поймать.Как я могу поймать SIGINT в потоковой программе python?

Почему и что делать?

Простая программа испытаний:

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

Попробуйте поражая Ctrl-C - ничего не происходит.

ответ

8

Нити и сигналы не смешиваются. В Python это даже больше, чем снаружи: сигналы только когда-либо доставляются в один поток (основной поток); другие потоки не получат сообщение. Для прерывания потоков, отличных от основного потока, вы ничего не можете сделать. Они не поддаются контролю.

Единственное, что вы можете сделать здесь, это ввести канал связи между основным потоком и любыми потоками, которые вы запускаете, используя модуль queue. Затем вы можете отправить сообщение в поток и завершить его (или делать все, что захотите), когда оно увидит сообщение.

Альтернативно, и это часто очень хорошая альтернатива - не использовать потоки. Однако, что использовать, во многом зависит от того, чего вы пытаетесь достичь.

+3

Главной нить не получают SIGINT либо. В противном случае я мог бы просто поймать его и вызвать sys.exit (0). –

+0

Кажется, я ошибаюсь. Основная тема действительно получает SIGINT. Спасибо! –

+0

Но я не понимаю, почему sys.exit (0) не работает в обработчике сигналов. –

-1

В принципе, вы можете проверить, выдал ли родитель сигнал, прочитав очередь во время работы. Если родитель получает SIGINT, то она выдает сигнал через очередь (в данном случае ничего) и детям завернуть свою работу и выйти ...

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

Пожалуйста, подумайте о том, почему этот код работает. Сбрасывание кода обычно не рекомендуется на StackOverflow. – rayryeng

Смежные вопросы