代码之家  ›  专栏  ›  技术社区  ›  Emilio

线程忽略键盘中断异常

  •  43
  • Emilio  · 技术社区  · 14 年前

    我运行这个简单的代码:

    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线程忽略了我的 + 键盘中断,无法打印 Received Keyboard Interrupt

    5 回复  |  直到 6 年前
        1
  •  68
  •   unutbu    14 年前

    尝试

    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 ,主要过程是跳出 try...except 封锁太早,所以 KeyboardInterrupt 没有被抓住。我的第一个想法是 thread.join ,但这似乎阻止了主进程(忽略键盘中断),直到 thread 完成了。

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

        2
  •  12
  •   Community CDub    8 年前

    总结中建议的更改 the comments ,以下内容对我很有用:

    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()
    
        3
  •  5
  •   yaccob    9 年前

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

    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'
    
        4
  •  0
  •   Albert    10 年前

    我的解决办法是猴子补丁 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
    
        5
  •  0
  •   personal_cloud    7 年前

    try ... except signal.pause() 在里面 是的 main()

    当心 import lock 不过。我猜这就是Python在默认情况下不解决ctrl-C的原因。