[英]How to assure the multiprocessing queue is empty
下面的代码首先启动多个过程。 然后,它运行while True
循环,检查queue
对象。 最后,它迭代过程以检查是否还活着。 所有过程完成后,它将breaks
while
循环。 不幸的是,它在queue
对象不为空时发生。 在没有将数据存储在queue
情况下中断循环可能很容易检查数据丢失。 如何修改代码逻辑,以确保在中断循环之前queue
对象为空?
import time, multiprocessing, os
logger = multiprocessing.log_to_stderr()
def foo(*args):
for i in range(3):
queue = args[0]
queue.put(os.getpid())
items = dict()
for i in range(5):
queue = multiprocessing.Queue()
proc = multiprocessing.Process(target=foo, args=(queue,))
items[proc] = queue
proc.start()
time.sleep(0.1)
while True:
time.sleep(1)
for proc, queue in items.items():
if not queue.empty():
print(queue.get())
if not True in [proc.is_alive() for proc in items]:
if not queue.empty():
logger.warning('...not empty: %s' % queue.get())
break
同步问题,再次。 当您检查队列发现它为空时,不能保证将来不会有新项目出现。
您可以在子流程完成其工作时将标记放置在队列中,以通知队列中将没有更多项目。 父进程可能会耗尽队列,直到得到前哨。 这也是multiprocessing.Pool
使用的方法。 您可以在此处将None
用作哨兵:
def foo(*args):
for i in range(3):
queue = args[0]
queue.put(os.getpid())
queue.put(None)
...
while items:
for proc in tuple(items.keys()):
queue = items[proc]
if not queue.empty():
r = queue.get()
print(r)
if r is None:
proc.join()
del items[proc]
time.sleep(0.1)
一个有效的解决方案在下面发布。 该方法不是使用Process.run
运行proc,而是使用multiprocessing.pool.ThreadPool.map_async
方法启动进程而不会阻塞。 然后,使用multiprocessing.Queue
对象存储可由MainProcess运行的foo
函数访问的数据。
import time, multiprocessing, Queue
from multiprocessing.pool import ThreadPool
logger = multiprocessing.log_to_stderr()
def foo(args):
queue = args[0]
arg = args[1]
for i in range(3):
time.sleep(2)
queue.put([arg, time.time()])
pool = ThreadPool(processes=4)
queue = multiprocessing.Queue()
map_result = pool.map_async(foo, [(queue, arg) for arg in range(3)])
logger.warning("map_result: %s" % map_result)
map_result.wait(timeout = 10)
if not map_result.ready():
message = '%s is timed out and terminated.' % pool
log.error(message)
pool.terminate()
raise Exception(message)
while not queue.empty():
if queue.empty():
break
logger.warning("queue_data: %r" % queue.get(True, 0.1))
pool.close()
pool.join()
#encoding:utf-8
from multiprocessing import Pool, Manager
def tiny(q, j):
if len(j) < 100:
q.put(j+j[-1])
print " Done!", j
q.put(-1)
return
queue = Manager().Queue()
pool = Pool(processes=10)
pool.apply_async(tiny, (queue, "A"))
pool.apply_async(tiny, (queue, "B"))
pool.apply_async(tiny, (queue, "C"))
created = 3
fininshed = 0
while created > fininshed:
i = queue.get(True, None)
if isinstance(i, int):
fininshed += 1
else:
created += 1
pool.apply_async(tiny, (queue, i))
pool.close()
pool.join()
print [worker.is_alive() for worker in pool._pool]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.