【问题标题】:Stop a main thread from child thread从子线程停止主线程
【发布时间】:2013-05-05 18:35:22
【问题描述】:

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

提前致谢

【问题讨论】:

    标签: python multithreading exception


    【解决方案1】:

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

    所以我的建议是您的主线程启动 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(尽管您可能决定在ThreadA 中使用try-except,以使其干净地退出)。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-27
        • 1970-01-01
        • 2019-01-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多