首页 > 解决方案 > KeyboardInterrupt 在 Python 中无法停止线程

问题描述

我想使用两个线程从实时流中捕获和存储图像。我想用 Ctrl + C 键盘中断来停止线程。我正在调用一个函数

如果名称== “主要”:

但它不工作。我在 anaconda 环境中使用 spyder。我也使用终端尝试过,但它不起作用。谁能解释它为什么以及如何工作?

代码如下

class ImageGrabber(threading.Thread):
def __init__(self, ID):
    threading.Thread.__init__(self)
    self.ID=ID
    self.cam=cv2.VideoCapture(ID)
    self.fps = self.cam.get(cv2.CAP_PROP_FPS)
    self.w=self.cam.get(cv2.CAP_PROP_FRAME_WIDTH)
    self.h=self.cam.get(cv2.CAP_PROP_FRAME_HEIGHT)
    (self.grabbed, self.frame) =self.cam.read()
    print(f"Camera Opened with fps {self.fps}, width = {self.w}, and height = {self.h}")
    plt.imshow(self.frame)
    plt.show()
    self.stopped = False
    
def run(self):
    global frames
    global exitProgram
    # print("Entered Grabbed Run ******:")
    while not self.stopped:
        if not self.grabbed or exitProgram is True:
            print("Exit Command reached")
            self.stop()
            self.cam.release()
        else:
            (self.grabbed, self.frame) =self.cam.read()
            frames.put(self.frame)
            
def stop(self):
    self.stopped = True

class ImageSaver(threading.Thread):
def __init__(self,grabber,codec):
     
    threading.Thread.__init__(self)
    global saveImages
    fourcc = cv2.VideoWriter_fourcc(*codec)
    self.fName=self.getDateStamp() + '.avi'
    if saveImages is False:
        self.out = cv2.VideoWriter(self.fName, fourcc,grabber.fps ,(int(grabber.w),int(grabber.h)))
    
def getDateStamp(self):

    filedate = str(datetime.now())
    filedate = filedate[0:-7]
    filedate = filedate.replace(':', '_')
    filename = filedate 
#print(filename)

    return filename
def run(self):
    global frames
    global saveImages
    while True:
        # print("Entered Loop 1:")
        if(not frames.empty()):
            # print("Entered frame showing:")
            self.Currframe=frames.get()
            if saveImages is False:
                self.out.write(self.Currframe)
            else:
                self.imgName=self.getDateStamp() + '.tiff'
                cv2.imwrite(self.imgName,self.Currframe)
            print(f"Queue Size in writing = {frames.qsize()}")
            # print("Show Image")
        elif exitProgram is True:
            print("Exit Command Main reached")
            print(f"Final Queue Size at exit = {frames.qsize()}")
            break

def initStart(*args):

    argsList=sum(list(args),[])
    argsLen = len(argsList)

    if(argsLen==2):
        ID = int(argsList[0])
        codec = argsList[1]
    elif(argsLen==1):
        ID = int(argsList[0])
        codec = 'XVID'
    else:
        ID = 0
        codec = 'XVID'
    
    grabber = ImageGrabber(ID)
    saver = ImageSaver(grabber,codec)

    grabber.start()
    saver.start()
    e = threading.Event()
    # main.join()
    # grabber.join()

    print ('Press CTRL-C to interrupt')
    while grabber.isAlive():
        try: 
            time.sleep(1) #wait 1 second, then go back and ask if thread is still alive
            print ('Sleep...')
        except: #if ctrl-C is pressed within that second,
                              #catch the KeyboardInterrupt exception
                
            e.set() #set the flag that will kill the thread when it has finished
            exitProgram=True
            print ('Exiting...')
            grabber.join()
            saver.join()

if __name__ == "__main__":
    full_cmd_arguments = sys.argv
    # Keep all but the first. First contains the path of script or file
    argument_list = full_cmd_arguments[1:]
    initStart(argument_list)

如果我以这样的方式更改程序,即在没有任何功能的情况下调用keyboardInterrupt,那么它就可以工作

grabber = ImageGrabber(0)
main = Main(grabber,'XVID')

grabber.start()
main.start()
e = threading.Event()
print ('Press CTRL-C to interrupt')
while grabber.isAlive():
    try: time.sleep(1) #wait 1 second, then go back and ask if thread is 
 
    except KeyboardInterrupt: #if ctrl-C is pressed within that second,
                          #catch the KeyboardInterrupt exception
            
        e.set() #set the flag that will kill the thread when it has finished
        exitProgram=True
        print ('Exiting...')
        grabber.join()
        main.join()

上面的代码直接作为python脚本调用,然后它就可以工作了。任何原因?

任何想法?它是如何工作的?

标签: pythonmultithreadingkeyboardinterrupt

解决方案


推荐阅读