Python线在Python中带有Ctrl-C退出



我的python多线程程序如下。如果我在5秒内按CTRL C,它将进入键盘Interrupt异常

运行代码超过15秒的运行无法响应Ctrl c。如果我在15秒后按Ctrl C,则无法正常工作。它是不抛出键盘Interrupt异常。可能是什么原因 ?我在Linux上进行了测试。

#!/usr/bin/python
import os, sys, threading, time
class Worker(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    # A flag to notify the thread that it should finish up and exit
    self.kill_received = False
  def run(self):
      while not self.kill_received:
          self.do_something()
  def do_something(self):
      [i*i for i in range(10000)]
      time.sleep(1)
def main(args):
    threads = []
    for i in range(10):
        t = Worker()
        threads.append(t)
        t.start()
    while len(threads) > 0:
        try:
            # Join all threads using a timeout so it doesn't block
            # Filter out threads which have been joined or are None
            threads = [t.join(1) for t in threads if t is not None and t.isAlive()]
        except KeyboardInterrupt:
            print "Ctrl-c received! Sending kill to threads..."
            for t in threads:
                t.kill_received = True
if __name__ == '__main__':
  main(sys.argv)

在第一次执行

之后
threads = [t.join(1) for t in threads if t is not None and t.isAlive()]

您的变量threads包含

[None, None, None, None, None, None, None, None, None, None]

第二个执行后,相同的变量threads包含:

[]

此时,len(threads) > 0是错误的,您可以摆脱时循环。您的脚本仍在运行,因为您仍然有10个线程仍处于活动状态,但是由于您不再在try/Block(捕获键盘插发)中,因此您不能停止使用Ctrl C

在您的脚本中添加一些打印,以查看我所描述的内容:

#!/usr/bin/python
import os, sys, threading, time
class Worker(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    # A flag to notify the thread that it should finish up and exit
    self.kill_received = False
  def run(self):
      while not self.kill_received:
          self.do_something()
  def do_something(self):
      [i*i for i in range(10000)]
      time.sleep(1)
def main(args):
    threads = []
    for i in range(10):
        t = Worker()
        threads.append(t)
        t.start()
        print('thread {} started'.format(i))
    while len(threads) > 0:
        print('Before joining')
        try:
            # Join all threads using a timeout so it doesn't block
            # Filter out threads which have been joined or are None
            threads = [t.join(1) for t in threads if t is not None and t.isAlive()]
            print('After join() on threads: threads={}'.format(threads))
        except KeyboardInterrupt:
            print("Ctrl-c received! Sending kill to threads...")
            for t in threads:
                t.kill_received = True
    print('main() execution is now finished...')
if __name__ == '__main__':
  main(sys.argv)

和结果:

$ python thread_test.py
thread 0 started
thread 1 started
thread 2 started
thread 3 started
thread 4 started
thread 5 started
thread 6 started
thread 7 started
thread 8 started
thread 9 started
Before joining
After join() on threads: threads=[None, None, None, None, None, None, None, None, None, None]
Before joining
After join() on threads: threads=[]
main() execution is now finished...

实际上,Ctrl C在15秒后不停止工作,而是在10或11秒之后。这是创建和启动10个线程(少于一秒钟)并在每个线程上执行加入(1)所需的时间。

来自文档的提示:

作为join()始终返回无,您必须在join()之后拨打isalive()来决定是否发生了超时 - 如果线程还活着,则join()呼叫定时出现。

要在上面的海报上跟进,isalive()被更名为is_alive()在Python 3.9.6

上尝试了

完整代码:

#!/usr/bin/python
import os, sys, threading, time
class Worker(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    # A flag to notify the thread that it should finish up and exit
    self.kill_received = False
  def run(self):
      while not self.kill_received:
          self.do_something()
  def do_something(self):
      [i*i for i in range(10000)]
      time.sleep(1)
def main(args):
    threads = []
    for i in range(10):
        t = Worker()
        threads.append(t)
        t.start()
        print('thread {} started'.format(i))
    while len(threads) > 0:
        print('Before joining')
        try:
            # Join all threads using a timeout so it doesn't block
            # Filter out threads which have been joined or are None
            threads = [t.join(1) for t in threads if t is not None and t.is_alive()]
            print('After join() on threads: threads={}'.format(threads))
        except KeyboardInterrupt:
            print("Ctrl-c received! Sending kill to threads...")
            for t in threads:
                t.kill_received = True
    print('main() execution is now finished...')
if __name__ == '__main__':
  main(sys.argv)

相关内容

  • 没有找到相关文章

最新更新