如何确保多处理队列为空

时间:2018-11-01 03:22:49

标签: python multiprocessing

下面的代码首先启动多个进程。然后,它运行一个--zabbix-template循环,检查while True对象。最后,它迭代过程以检查是否还活着。完成所有过程后,将进行queue breaks循环。 不幸的是,它发生在while对象不为空的情况下。在没有获取数据存储在queue中的情况下中断循环可能很容易导致数据丢失。如何修改代码逻辑,以确保在中断循环之前queue对象为空?

queue

3 个答案:

答案 0 :(得分:2)

再次出现同步问题。当您检查队列发现它为空时,不能保证将来不会有新项目出现。

您可以在子进程完成其工作时将标记放置在队列中,以通知队列中将没有更多项目。父进程可能会耗尽队列,直到得到前哨。这也是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)

答案 1 :(得分:0)

一个有效的解决方案在下面发布。该方法不是使用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()

答案 2 :(得分:0)

#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]