Python进程间队列溢出

时间:2013-07-29 16:17:11

标签: python queue producer-consumer interprocess

我有一个N消费者的生产者设置。

生产者侦听一个接收大量TCP消息(每分钟10,000个)的套接字,读取这些数据并将其放入工作队列中。

我已经设置为从队列中读取的工作人员如下:

iterations = 0
work_iterations = 0
while True:
  try:
    iterations += 1
    data = queue.get(block=False)
    work_iterations +=1
    do_work(data)
  except Queue.Empty:
    time.sleep(0.001) #avoid high CPU usage


  if iterations == 100:
    load = float(work_iterations/iterations)
    print load
    iterations = 0
    work_iterations = 0

这是简化的代码,但您可以看到我试图查看工作负载,但是看看工作人员实际上能够从队列中取出工作量的100次迭代。如果负载始终为100/100,那么我知道生产者/消费者队列正在积压。从理论上讲,这个应该工作。

我在输出中看到的是很多0.97,0.99和非常少的1.0。但是队列确实会在几分钟内填满(它的大小限制为10,000),我必须开始在Producer端丢弃数据。任何人都可以阐明为什么会这样吗?如果工作进程平均得到97/100次迭代,那意味着队列应该接近空的否?

2 个答案:

答案 0 :(得分:0)

当您调用queue.get(block = False)时,即使队列实际上不为空,也可能引发Queue.Empty。如果当前进程无法获取锁以访问队列,则无论队列中实际有多少项,都将引发Queue.Empty。

快速查看multiprocessing / queues.py中的Queue.get()代码:

126    if not self._rlock.acquire(block, timeout):
127        raise Empty

请注意,在引发异常之前,没有检查队列实际上有多满。由于你有很多信息被排队,我怀疑Queue.Empty被提出几次,这实际上是由于生产者在入队时持有锁,导致你的工人尝试访问队列失败。

您可以通过对代码进行少量更改来检查此问题:

except Queue.Empty:
    print queue.qsize() # returns the approximate number of elements in the queue

正如the documentation所说,这个数字并不完全可靠。但是,由于您在队列中处理如此大量的项目,因此它应足够接近,以告诉您队列是否接近0或10,000。

答案 1 :(得分:-1)

如果删除block = Flase和time.sleep()怎么办? 你将无法计算工人。