2015-04-15 5 views
3

Мне не удается понять, почему мой SIGINT никогда не улавливается частью кода ниже.Python SIGINT не пойман

#!/usr/bin/env python 
from threading import Thread 
from time import sleep 
import signal 

class MyThread(Thread): 
    def __init__(self): 
     Thread.__init__(self) 
     self.running = True 

    def stop(self): 
     self.running = False 

    def run(self): 
     while self.running: 
      for i in range(500): 
       col = i**i 
       print col 
       sleep(0.01) 

global threads 
threads = [] 

for w in range(150): 
    threads.append(MyThread()) 

def stop(s, f): 
    for t in threads: 
     t.stop() 

signal.signal(signal.SIGINT, stop) 

for t in threads: 
    t.start() 

for t in threads: 
    t.join() 

Чтобы очистить этот код, который я предпочел бы попробовать/за исключением присоединиться() и закрытия всех потоков в случае исключения, будет работать?

+0

Возможный дубликат [Inte прерывистый поток присоединяется к Python] (https://stackoverflow.com/questions/631441/interruptible-thread-join-in-python) –

ответ

6

Одна из проблем многопоточности в python заключается в том, что join() более или менее отключает сигналы.

Это связано с тем, что сигнал может быть доставлен только в основной поток, но основной поток уже занят выполнением join(), и соединение не прерывается.

Вы можете вывести это из документации signal модуля

Некоторые уход должны быть приняты, если оба сигнала и нити используются в одной и той же программы. Основное, что нужно помнить при использовании сигналов и потоков одновременно: всегда выполнять операции signal() в основном потоке выполнения. Любой поток может выполнять сигналы тревоги(), getsignal(), pause(), setitimer() или getitimer(); только основной поток может установить новый обработчик сигналов, а основной поток будет единственным, кто будет принимать сигналы (это обеспечивается сигнальным модулем Python, даже если реализация базового потока поддерживает отправку сигналов в отдельные потоки). Это означает, что сигналы не могут использоваться как средство межпоточной связи. Вместо этого используйте блокировки.

Вы можете работать свой путь вокруг него, занятыми-цикла по операции соединения:

for t in threads: 
    while t.isAlive(): 
     t.join(timeout=1) 

Это, однако, ни к эффективной:

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

Некоторые подробности представлены здесь:

Python program with thread can't catch CTRL+C

отчеты об ошибках для этой проблемы с обсуждением основного вопроса можно найти здесь:

https://bugs.python.org/issue1167930

https://bugs.python.org/issue1171023