为何相同multiprocessing代码在repl.it运行时输出结果不一致?
为什么你的multiprocessing Queue代码输出不稳定?
先看一下你贴的代码:
from multiprocessing import Queue colors = ['red', 'green', 'blue', 'black'] cnt = 1 # instantiating a queue object queue = Queue() print('pushing items to queue:') for color in colors: print('item no: ', cnt, ' ', color) queue.put(color) cnt += 1 print('\npopping items from queue:') cnt = 1 while not queue.empty(): print('item no: ', cnt, ' ', queue.get()) cnt += 1
首先得澄清一个点:你这段代码根本没用到多进程——只是用了multiprocessing.Queue这个类,但全程都是在主进程里读写队列,所以问题和多进程机制本身没啥关系,主要是两个容易踩的坑:
1. multiprocessing.Queue.empty()是不可靠的
官方文档早就明确说了,empty()的返回值不能作为队列是否为空的准确判断依据。哪怕是单进程环境下,队列内部的状态同步可能存在微小延迟,导致你调用empty()时得到True,但实际上队列里还有元素没取出来——这就会让你的while循环提前终止,出现只输出部分出队元素甚至完全没出队输出的情况。
2. repl.it的输出缓冲问题
repl.it的控制台输出是带缓冲的,默认情况下print的内容不会立刻显示到屏幕上,而是攒到一定量才刷新。如果你的程序因为empty()误判提前结束,那缓冲里的内容可能还没来得及被输出,就会出现“只显示入队内容,没出队输出”的假象。
怎么解决?
给你两个简单的修改方案:
方案一:避免依赖empty(),用已知的元素数量循环
既然你知道入队的元素总数,直接循环对应次数取元素就行,完全不用判断队列是否为空:
from multiprocessing import Queue colors = ['red', 'green', 'blue', 'black'] cnt = 1 queue = Queue() print('pushing items to queue:', flush=True) for color in colors: print('item no: ', cnt, ' ', color, flush=True) queue.put(color) cnt += 1 print('\npopping items from queue:', flush=True) cnt = 1 # 用元素总数控制循环次数,彻底避开empty()的坑 for _ in range(len(colors)): print('item no: ', cnt, ' ', queue.get(), flush=True) cnt += 1
方案二:如果不需要多进程通信,改用标准库的queue.Queue
multiprocessing.Queue是专门为跨进程通信设计的,单进程下用标准库的queue.Queue会更稳定,它的empty()虽然也不推荐,但行为会更一致:
from queue import Queue # 换成标准库的Queue colors = ['red', 'green', 'blue', 'black'] cnt = 1 queue = Queue() print('pushing items to queue:', flush=True) for color in colors: print('item no: ', cnt, ' ', color, flush=True) queue.put(color) cnt += 1 print('\npopping items from queue:', flush=True) cnt = 1 while not queue.empty(): print('item no: ', cnt, ' ', queue.get(), flush=True) cnt += 1
另外,所有print语句加上flush=True,可以强制输出立刻刷新到控制台,避免repl.it的缓冲坑。
这样修改后,你的代码应该就能稳定输出所有入队和出队内容了。
内容的提问来源于stack exchange,提问作者Chidananda Nayak
相关产品推荐
相关产品推荐

