【发布时间】:2021-06-27 12:31:02
【问题描述】:
我想用键盘中断来停止线程化的 python 应用程序。一个线程捕获图像并将它们放入队列中,另一个线程将图像保存到硬盘。
代码在这里
import numpy as np
import threading
import time
from multiprocessing import Queue
import cv2
from datetime import datetime
import os
#import matplotlib.pyplot as plt
import sys
frames = Queue(50)
exitProgram = False
saveImages = True
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()
cv2.imwrite("testImage.png",self.frame)
print(f"Camera Opened with fps {self.fps}, width = {self.w}, and height = {self.h}")
self.stopped = False
# self.adjustB = adjustBrightness(0.75)
def run(self):
global frames
global exitProgram
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 imageSaveThread(threading.Thread):
def __init__(self,grabber,filePath):
threading.Thread.__init__(self)
global saveImages
self.dateTime = self.getDateStamp()
self.imgName = filePath + 'img_' + self.dateTime + '_'
self.cntr = 0
def getDateStamp(self):
filedate = str(datetime.now())
filedate = filedate[0:-7]
filedate = filedate.replace(':', '_')
filename = filedate
return filename
def run(self):
global frames
while True:
if(not frames.empty()):
self.Currframe=frames.get()
cv2.imwrite(self.imgName + str(self.cntr).zfill(6) + '.png',self.Currframe)
self.cntr = self.cntr + 1
print(f"Queue Size in writing = {frames.qsize()} and fram number = {self.cntr}")
elif exitProgram is True:
print("Exit Command imageSaveThread reached")
print(f"Final Queue Size at exit = {frames.qsize()}")
break
def main():
if saveImages == True:
savefilePath = 'D:/111/'
grabber = ImageGrabber(0)
imageSaveThr = imageSaveThread(grabber,savefilePath)
grabber.start()
imageSaveThr.start()
e = threading.Event()
# imageSaveThread.join()
# grabber.join()
print ('Press CTRL-C to interrupt')
while grabber.isAlive():
try:
time.sleep(5) #wait 1 second, then go back and ask if thread is still alive
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()
imageSaveThr.join()
else:
videoCodec = 'h264'
videoExt = 'mkv'
if __name__ == '__main__':
main()
我替换了main函数并直接调用程序然后它工作并像下面的代码一样退出线程
import numpy as np
import threading
import time
from multiprocessing import Queue
import cv2
from datetime import datetime
import os
#import matplotlib.pyplot as plt
import sys
frames = Queue(50)
exitProgram = False
saveImages = True
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()
cv2.imwrite("testImage.png",self.frame)
print(f"Camera Opened with fps {self.fps}, width = {self.w}, and height = {self.h}")
self.stopped = False
# self.adjustB = adjustBrightness(0.75)
def run(self):
global frames
global exitProgram
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 imageSaveThread(threading.Thread):
def __init__(self,grabber,filePath):
threading.Thread.__init__(self)
global saveImages
self.dateTime = self.getDateStamp()
self.imgName = filePath + 'img_' + self.dateTime + '_'
self.cntr = 0
def getDateStamp(self):
filedate = str(datetime.now())
filedate = filedate[0:-7]
filedate = filedate.replace(':', '_')
filename = filedate
return filename
def run(self):
global frames
while True:
if(not frames.empty()):
self.Currframe=frames.get()
cv2.imwrite(self.imgName + str(self.cntr).zfill(6) + '.png',self.Currframe)
self.cntr = self.cntr + 1
print(f"Queue Size in writing = {frames.qsize()} and fram number = {self.cntr}")
elif exitProgram is True:
print("Exit Command imageSaveThread reached")
print(f"Final Queue Size at exit = {frames.qsize()}")
break
savefilePath = 'D:/111/'
grabber = ImageGrabber(0)
imageSaveThr = imageSaveThread(grabber,savefilePath)
grabber.start()
imageSaveThr.start()
e = threading.Event()
# imageSaveThread.join()
# grabber.join()
print ('Press CTRL-C to interrupt')
while grabber.isAlive():
try:
time.sleep(5) #wait 1 second, then go back and ask if thread is still alive
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()
imageSaveThr.join()
我无法理解原因。谁能告诉我是什么原因?
【问题讨论】:
-
如果变量位于函数中任何位置的赋值左侧,则该变量是该函数的局部变量(如果未另行声明)并且可能会隐藏同名的全局变量(可以'然后在这个函数中修改)。
-
如果您在谈论
exitProgram变量,现在我将其更改为全局,无论它在哪里使用,但同样的问题。问题是按下 ctrl + c 时不会使其进入try catch块的except部分 -
它没有进入
while grabber.isAlive():循环,我改了while grabber.is_alive()它在windows10中工作
标签: python multithreading python-multithreading