python 多线程下如何正确响应 ctrl + c

我在测试多线程时,发现有写模块无法在多线程下正确响应 ctrl + c,经过我测试,应该为 paste 模块所致,请问这种情况如何处理较好?

import sys
import threading
import time

import bottle

HttpThread1 = None
HttpThread2 = None


@bottle.route('/hello')
def hello():
    return "Hello World!"


def server1():
    bottle.run(server='paste', port=8081)


def server2():
    bottle.run(server='paste', port=8082)


def info():
    print(threading.active_count())


try:
    HttpThread1 = threading.Thread(target=server1, args=())
    HttpThread1.setDaemon(True)
    HttpThread1.start()

    HttpThread2 = threading.Thread(target=server2, args=())
    HttpThread2.setDaemon(True)
    HttpThread2.start()

    while True:
        info()
        time.sleep(1)
except KeyboardInterrupt:
    sys.exit(1)

我现有的解决方案为采用 multiprocessing 库来解决程序退出问题。

阅读 5.6k
2 个回答

threading.Condition

python3

import threading
import time

class 子线程(threading.Thread):
    def __init__(self):
        super().__init__()
        
        self.cond = threading.Condition() # 条件锁
        self.isStoped = False # 结束标志

    def run(self):
        print('线程开始')
        n = 0
        while 1:
            with self.cond: # 锁
                n += 1
                print(n) # 要完成的事
                self.cond.wait(1) # 休眠 1秒
                if self.isStoped:break # 退出线程循环

        print('线程结束')
    
    def 结束线程(self):
        with self.cond: # 锁
            self.isStoped = True # 设置结束标志
            self.cond.notify() # 唤醒休眠的线程,立即结束。
    

# 主线程
if __name__ == '__main__':
    t = 子线程()
    t.start()

    try:
        while 1:
            time.sleep(0.1) # 等待ctrl-c,让线程干事
    except KeyboardInterrupt:
        t.结束线程()   
    finally:
        t.结束线程()

    t.join()    
    input('按<Enter>键退出')
    

@同意并接受 @Yujiaao 这样做不行的,对于可以休眠的子线程程序,这样做当然没有问题。

但是, bottle 和 paste 是做 webserver 的,也就是说 run 中运行的是不会结束的,而 bottle 又没有开放 paste 的 API (至少调用没有开放)。

ctrl + c 需要先把事件透传到子线程上去,先结束子线程,然后结束主线程。

还没测试信号处理,我现在测试关闭信号处理,看看能不能解决。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题