61

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

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。为什么?这段代码有什么问题?

4

5 回答 5

72

尝试

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

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

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

于 2010-09-24T14:51:04.303 回答
13

总结评论中建议 更改,以下内容对我很有效:

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()
于 2014-05-01T17:30:18.883 回答
7

对 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 '\n! Received keyboard interrupt, quitting threads.\n'
于 2016-02-26T08:36:28.773 回答
0

我的(hacky)解决方案是这样的猴子补丁Thread.join()

def initThreadJoinHack():
  import threading, thread
  mainThread = threading.currentThread()
  assert isinstance(mainThread, threading._MainThread)
  mainThreadId = thread.get_ident()
  join_orig = threading.Thread.join
  def join_hacked(threadObj, timeout=None):
    """
    :type threadObj: threading.Thread
    :type timeout: float|None
    """
    if timeout is None and thread.get_ident() == mainThreadId:
      # This is a HACK for Thread.join() if we are in the main thread.
      # In that case, a Thread.join(timeout=None) would hang and even not respond to signals
      # because signals will get delivered to other threads and Python would forward
      # them for delayed handling to the main thread which hangs.
      # See CPython signalmodule.c.
      # Currently the best solution I can think of:
      while threadObj.isAlive():
        join_orig(threadObj, timeout=0.1)
    else:
      # In all other cases, we can use the original.
      join_orig(threadObj, timeout=timeout)
  threading.Thread.join = join_hacked
于 2015-03-06T13:27:34.347 回答
0

把它放在每个线程中,对我来说try ... except也是一个真正的作品。signal.pause() main()

不过要注意导入锁。我猜这就是 Python 默认不解决 ctrl-C 的原因。

于 2017-09-21T23:39:20.013 回答