提前感谢您的回答。
让一个线程“控制”其父线程不是一个好的做法。更合理的方式是主线程管理/监视/控制它启动的线程。
因此,我的建议是您的主线程启动两个线程:其中一个是您已经拥有的线程,在某个时刻完成/引发异常,另一个是读取用户输入的线程。现在,主线程等待(使用join
)前者完成,并在完成后退出。
from threading import Thread
import time
class ThreadA(Thread):
def run(self):
print 'T1: sleeping...'
time.sleep(4)
print 'T1: raising...'
raise RuntimeError('bye')
class ThreadB(Thread):
def __init__(self):
Thread.__init__(self)
self.daemon = True
def run(self):
while True:
x = raw_input('T2: enter some input: ')
print 'GOT:', x
t1 = ThreadA()
t2 = ThreadB()
t1.start()
t2.start()
t1.join() # wait for t1 to finish/raise
print 'done'
由于ThreadB是守护进程,我们不需要显式地停止它,也不需要加入它。当主线程退出时,它也会退出。
我认为,没有必要使用像信号这样的底层东西。这个解决方案甚至不需要使用try-except(尽管您可能决定在ThreadA中使用try-except,以使其干净地退出)。
Python通过signal模块为您提供了访问此系统调用的方法,因此您可以为SIGINT
注册信号处理程序并执行任何操作。顺便说一下,默认的SIGINT
处理程序只是引发KeyboardInterrupt
异常,因此如果您不想使用信号,可以将整个程序放在try / except结构中,并获得更多或更少相同的效果。由于您希望在子线程崩溃时停止主线程,因此只需将整个while循环放在except Exception:
try-except块中即可。
这应该可以工作,但需要一些背景信息- Python的信号模块文档明确指出,当有多个线程运行时,只有主线程(即在进程启动时创建的线程)将接收信号(对于您来说,这不应该有影响,因为您希望在主线程中接收信号)。因此,信号处理程序仅在一个线程中执行,而不是在所有线程中执行。为了使所有线程响应信号停止,您需要主线程的信号处理程序向其他子线程传达停止消息。这可以通过不同的方式完成,最简单的方法是让主线程翻转所有子线程持有引用的布尔变量的值。这只是为了捕获一个场景,其中一个子线程崩溃并发送信号给主线程以优雅地关闭,使用上述方法,您可以关闭子线程而不会突然终止它们。