1

我有一个简单的设置:

Producer 从相机读取一组图像,并使用 numpy.row_stack() 将它们连接起来。生成的数组被放入 Queue.Queue。

消费者使用 Queue.get() 不断等待数据,一旦收到数据,它就会将图像保存到文件中。无论出于何种原因,该进程都会泄漏内存,就像没有明天一样。如果我不将图像放入线程队列,则不会发生泄漏。显然,泄漏的不是队列,而是我的保存图像功能中的一些东西。特别是在创建临时文件部分。这是实现:

def _createTmpFile(self, image):
    filename = '/tmp/imgTemp.gray'
    with open(filename, 'wb') as fp: 
        scaled  = image * 16
        big     = numpy.asmatrix(scaled, dtype='>i2')
        fp.write(big.tostring())
    return filename

def _saveImage(self, filename, image):
    tmpFile = self._createTmpFile(image)
    try:
        # Call a blocking sub process command to convert the image:
        command = ('convert -size %dx%d -depth 16 -endian MSB' % ( image.shape[1], image.shape[0])).split(' ')
        command += [tmpFile, '/tmp/' + os.path.basename(filename)]
        log.debug("command being called: %s" % str(command))
        subprocess.call(command)
        os.unlink(tmpFile)
        log.info("Image %s is saved." % filename)
    except Exception as e:
        log.exception()
        log.warning("Failed to save image %s" % filename)

我没有看到任何特别突出的东西,这会导致内存泄漏。有任何想法吗?

更新:经过彻底分析,问题变得非常简单——生产者创建图像的速度比消费者保存图像的速度快得多,从而填满了队列。当我取消对图像的请求时,我会排空队列,但似乎 GC 速度不够快,无法拾取大量图像,因此它们阻塞了内存。

4

1 回答 1

0

subprocess.call() 是原因,您应该在其中放置一个等待左右的命令,和/或让它进入一个新的终端左右,并带有一些 kwarg。因为否则它会启动调用,然后在队列中它会做类似的事情,(使用命令行的事情对子进程来说很棘手)

我认为带有 shell=True 的 check_call() 应该可以工作,而不是 subprocess.call,但我也不完全确定这一点。我曾经遇到过类似的问题,我认为解决了

另一个原因可能是在你的队列中,如果你多次调用 createTmpFile,你写入同一个临时图像,所以多个图像相互覆盖等等?我猜这可能会导致内存泄漏

于 2013-07-16T08:17:50.060 回答