我无法理解为什么我的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()
要清理此代码,我更喜欢尝试/除了join()并在异常的情况下关闭所有线程,这会有用吗?
答案 0 :(得分:7)
python中多线程的一个问题是join()
或多或少会禁用信号。
这是因为信号只能传递到主线程,但主线程已经忙于执行join()
并且连接不可中断。
您可以从signal
模块
如果在同一程序中使用信号和线程,则必须小心。在同时使用信号和线程时要记住的基本要点是:始终在执行的主线程中执行signal()操作。任何线程都可以执行alarm(),getsignal(),pause(),setitimer()或getitimer();只有主线程可以设置一个新的信号处理程序,主线程将是唯一一个接收信号(这是由Python信号模块强制执行的,即使底层线程实现支持发送信号到个别线程)。这意味着信号不能用作线程间通信的手段。改为使用锁。
您可以通过忙于循环连接操作来解决它:
for t in threads:
while t.isAlive():
t.join(timeout=1)
然而,这没有效率:
使用超时调用join()的解决方法有一个缺点: Python的线程等待例程每秒轮询20次 任何超时。所有这些轮询都意味着大量的CPU 在一台空闲的笔记本电脑上中断/唤醒并排空 电池更快。
此处提供了更多详细信息:
Python program with thread can't catch CTRL+C
可以在此处找到关于此问题的Bug报告以及对基础问题的讨论: