簡體   English   中英

Python線程在Python中以ctrl-c退出

[英]Python threads exit with ctrl-c in Python

我正在使用Python多線程程序,如下所示。 如果我在5秒內(大約)按ctrl + c,它將進入KeyboardInterrupt異常

運行超過15秒的代碼無法響應ctrl + c。 如果我在15秒后按ctrl + c,它不起作用。 不會拋出KeyboardInterrupt異常 可能是什么原因 ? 我在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為False,您將退出while循環。 你的腳本仍在運行,因為你有10個線程仍處於活動狀態,但由於你的try / except塊不再存在(要捕獲KeyboardInterrupt),你不能停止使用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個線程(小於一秒)並在每個線程上執行join(1)(大約10秒)所需的時間。

來自doc的提示:

由於join()始終返回None,因此必須在join()之后調用isAlive()以確定是否發生超時 - 如果線程仍處於活動狀態,則join()調用超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM