简体   繁体   中英

Differences between python Queue.Queue and multiprocessing.Queue

My program does not close cleanly when I use the queue from the multiprocessing module (Python 2.7 on Windows) in place of Queue.Queue.

Eventually I want to process the frames in imgbuffer using a multiprocessing.Process and then pull back display data using a second queue. This does not work yet - it seems like Process.start() does nothing - but since I am having trouble making progress debugging the multiprocessing code, I thought I would pare back to the simplest code I have that is broken and see if anyone had ideas on what to try next.

import sys
from PySide import QtGui, QtCore
import cv2
import time, datetime
import multiprocessing
import Queue #needed separately for the Empty exception

def imageOpenCv2ToQImage(cv_img):
   height, width, bytesPerComponent = cv_img.shape
   bytesPerLine = bytesPerComponent * width;
   cv2.cvtColor(cv_img, cv2.cv.CV_BGR2RGB, cv_img)
   return QtGui.QImage(cv_img.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888)

class VideoWidget(QtGui.QLabel):
   def __init__(self):
      super(VideoWidget, self).__init__()

      self.imgbuffer = multiprocessing.Queue() 
      ############################################
      # hangs on quit using multiprocessing.Queue
      # works fine when I use Queue.Queue
      #########################################

      self.camera = cv2.VideoCapture(1) # camera ID depends on system: 0, 1, etc

      self.setGeometry(100, 100, 640, 480)
      self.setScaledContents(True)

      target_FPS = 30.0
      self.camera_timer = QtCore.QTimer()
      self.camera_timer.timeout.connect(self.on_camera_timer)
      self.camera_timer.start(1000.0/target_FPS)

      target_FPS = 40.0
      self.repaint_timer = QtCore.QTimer()
      self.repaint_timer.timeout.connect(self.on_repaint_timer)
      self.repaint_timer.start(1000.0/target_FPS)

   def shutdown(self):
      self.camera.release()

   def on_camera_timer(self):
      hello, cv_img = self.camera.read()
      tstamp = datetime.datetime.now()
      self.imgbuffer.put((tstamp, cv_img))

   def on_repaint_timer(self):
      try:
         tstamp, cv_img = self.imgbuffer.get(False)
         pixmap = QtGui.QPixmap.fromImage(imageOpenCv2ToQImage(cv_img))
         self.setPixmap(pixmap)
      except Queue.Empty:
         pass

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    widget = VideoWidget()
    app.aboutToQuit.connect(widget.shutdown)
    widget.show()
    sys.exit(app.exec_())

I figured it out... the answer was in the documentation after all:

https://docs.python.org/3/library/multiprocessing.html#pipes-and-queues

In particular:

They differ in that Queue lacks the task_done() and join() methods introduced into Python 2.5's queue.Queue class.

In my case, the solution seems to be adding this to the shutdown code:

self.imgbuffer.cancel_join_thread()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM