从子线程停止主线程

4
我正在编写一个Python程序,在主函数中启动了一个持续运行的线程。在启动线程后,主函数进入while循环并持续接收用户输入。如果子线程出现异常,我希望能够结束主函数。那么,最好的方法是什么?
提前感谢您的回答。
2个回答

7

让一个线程“控制”其父线程不是一个好的做法。更合理的方式是主线程管理/监视/控制它启动的线程。

因此,我的建议是您的主线程启动两个线程:其中一个是您已经拥有的线程,在某个时刻完成/引发异常,另一个是读取用户输入的线程。现在,主线程等待(使用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,以使其干净地退出)。


4

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

这应该可以工作,但需要一些背景信息- Python的信号模块文档明确指出,当有多个线程运行时,只有主线程(即在进程启动时创建的线程)将接收信号(对于您来说,这不应该有影响,因为您希望在主线程中接收信号)。因此,信号处理程序仅在一个线程中执行,而不是在所有线程中执行。为了使所有线程响应信号停止,您需要主线程的信号处理程序向其他子线程传达停止消息。这可以通过不同的方式完成,最简单的方法是让主线程翻转所有子线程持有引用的布尔变量的值。这只是为了捕获一个场景,其中一个子线程崩溃并发送信号给主线程以优雅地关闭,使用上述方法,您可以关闭子线程而不会突然终止它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接