线程忽略KeyboardInterrupt异常

Emi*_*lio 48 python events multithreading exception keyboardinterrupt

我正在运行这个简单的代码:

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')
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,它会打印出来

$ python prova.py
.
.
^C.
.
.
.
.
.
.
.
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored
Run Code Online (Sandbox Code Playgroud)

实际上python线程忽略我的Ctrl+ C键盘中断而不打印Received Keyboard Interrupt.为什么?这段代码有什么问题?

unu*_*tbu 59

尝试

try:
  thread=reqthread()
  thread.daemon=True
  thread.start()
  while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
  print '\n! Received keyboard interrupt, quitting threads.\n'
Run Code Online (Sandbox Code Playgroud)

如果没有调用time.sleep,主进程就会try...except过早地跳出块,因此KeyboardInterrupt不会被捕获.我的第一个想法是使用thread.join,但这似乎阻止了主进程(忽略KeyboardInterrupt)直到thread完成.

thread.daemon=True 导致主进程结束时线程终止.

  • 实际上不建议使用`thread.daemon = True`,因为它不允许线程清理留下的任何资源...... (12认同)
  • 我相信`join`的超时,即`while thread.isAlive:thread.join(5)`也可以保持主线程响应异常. (5认同)

rat*_*ray 10

总结中推荐的变化 意见,下面很适合我:

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()
Run Code Online (Sandbox Code Playgroud)


yac*_*cob 7

对 ubuntu 的解决方案稍作修改。

按照埃里克的建议删除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 '\n! Received keyboard interrupt, quitting threads.\n'
Run Code Online (Sandbox Code Playgroud)

  • 不错 - 但不幸的是 Windows 不支持 (4认同)