4

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

提前致谢

4

2 回答 2

7

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

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

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-exceptin ThreadA,让它干净地退出)。

于 2013-05-11T06:41:52.930 回答
4

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

这应该可行,但有一些背景信息 - Python 的信号模块文档明确指出,当多个线程运行时,只有主线程(即在您的进程启动时创建的线程)将接收信号(对您而言,这无关紧要,因为您想要主线程中的信号)。因此,信号处理程序将仅在一个线程中执行,而不是在所有线程中执行。为了让所有线程停止响应信号,您需要主线程的信号处理程序将停止消息传达给其他子线程。这可以通过不同的方式完成,最简单的方法是让主线程翻转所有子线程也持有引用的布尔变量的值。

于 2013-05-11T05:31:12.680 回答