从子线程停止主线程

时间:2013-05-11 02:00:35

标签: python multithreading exception

我正在编写一个python程序,在main函数中我正在启动一个连续运行的线程。启动线程后,main函数进入while循环,连续进行用户输入。如果子线程中有异常,我也想结束main函数。最好的方法是什么?

提前致谢

2 个答案:

答案 0 :(得分:7)

让线程“控制”其父级并不是一个好习惯。主线程管理/监视/控制它启动的线程更有意义。

所以我的建议是你的主线程启动2个线程:你已经拥有的线程,在某些时候完成/引发异常,以及一个读取用户输入。主线程现在等待(join s)前者完成,并在完成后退出。

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是守护进程,因此我们不必明确地使其停止,也不必加入它。当主线程退出时,它也会退出。

IMO,没有必要求助于像信号这样的低级别的东西。此解决方案甚至不需要使用try-except(尽管您可能希望在try-except中使用ThreadA,以使其完全退出)。

答案 1 :(得分:2)

Python允许您通过signal模块访问此系统调用,因此您可以为SIGINT注册信号处理程序并执行您喜欢的任何操作。顺便提一下,默认的SIGINT处理程序只会引发KeyboardInterrupt异常,因此如果您不想使用信号,可以将整个程序放在try / except结构中并获得或多或少的结果同样的效果。由于你想在子线程中的任何崩溃时停止主线程,只需将整个while循环放在except Exception: try-except块中。

这应该有用但是有些背景信息--Python的信号模块文档明确指出,当多个线程运行时,只有主线程(即你的进程启动时创建的线程)才会收到信号(对你来说无关紧要)因为你想要主线程中的信号)。所以信号处理程序只在一个线程中执行,而不是在所有线程中执行。为了使所有线程停止响应信号,您需要主线程的信号处理程序将停止消息传递给其他子线程。这可以通过不同的方式完成,最简单的方法是让主线程翻转所有子线程也拥有引用的布尔变量的值。这只是为了捕获一个子线程崩溃和一个信号被发送到主线程以正常关闭的场景,使用上面的方法可以关闭子线程而不会突然终止它们。