线程忽略了KeyboardInterrupt异常

68 投票
6 回答
80266 浏览
提问于 2025-04-16 04:33

我在运行这段简单的代码:

import threading, time

class reqthread(threading.Thread):    
    def run(self):
        for i in range(0, 10):
            time.sleep(1)
            print('.')

try:
    thread = reqthread()
    thread.start()
except (KeyboardInterrupt, SystemExit):
    print('\n! Received keyboard interrupt, quitting threads.\n')

但是当我运行它的时候,它输出了:

$ python prova.py
.
.
^C.
.
.
.
.
.
.
.
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored

实际上,Python 线程忽略了我按的 Ctrl+C 中断键,并没有打印出 Received Keyboard Interrupt。这是为什么呢?这段代码有什么问题吗?

6 个回答

9

这是对Ubuntu解决方案的一个小修改。

根据Eric的建议,去掉了 tread.daemon = True,并把原来的睡眠循环换成了signal.pause():

import signal

try:
  thread = reqthread()
  thread.start()
  signal.pause()  # instead of: while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
  print('Received keyboard interrupt, quitting threads.)
15

为了总结在这个这个评论中推荐的修改,以下内容对我来说效果很好:

try:
  thread = reqthread()
  thread.start()
  while thread.isAlive(): 
    thread.join(1)  # not sure if there is an appreciable cost to this.
except (KeyboardInterrupt, SystemExit):
  print '\n! Received keyboard interrupt, quitting threads.\n'
  sys.exit()
79

试试这个

try:
    thread = reqthread()
    thread.daemon = True
    thread.start()
    while True:
        time.sleep(100)
except (KeyboardInterrupt, SystemExit):
    print('Received keyboard interrupt, quitting threads.')
 

如果不调用 time.sleep,主程序会太早跳出 try...except 这个块,所以 KeyboardInterrupt 就捕捉不到了。我最开始的想法是用 thread.join,但这样会让主程序一直等着,直到这个 thread 完成,期间会忽略 KeyboardInterrupt

设置 thread.daemon=True 的话,线程会在主程序结束时自动终止。

撰写回答