多进程,使用Queue&池

时间:2015-06-20 12:23:22

标签: python python-2.7 queue multiprocessing

我有一个Producer进程,它运行并将结果放入队列中 我还有一个Consumer函数,它从队列中获取结果并处理它们,例如:

def processFrame(Q,commandsFile):
    fr = Q.get()
    frameNum = fr[0]
    Frame = fr[1]
    #        
    #   Process the frame
    #
    commandsFile.write(theProcessedResult)

我想使用多个进程运行我的使用者功能,它们的编号应由用户设置:

processes = raw_input('Enter the number of process you want to use: ')

我尝试使用Pool:

pool = Pool(int(processes))
pool.apply(processFrame, args=(q,toFile))

当我尝试这个时,它返回一个RuntimeError:Queue对象只应通过继承在进程之间共享。 这是什么意思?

我还尝试使用进程列表:

while (q.empty() == False):
    mp = [Process(target=processFrame, args=(q,toFile)) for x in range(int(processes))]
    for p in mp:
        p.start()
    for p in mp:
        p.join()

这个似乎在运行,但并不像预期的那样。 它在Queue的同一帧上使用多个进程,队列是否有锁? 此外,在这种情况下,我允许使用的进程数量必须除以没有残留的帧数(提醒) - 例如: 如果我有10帧我只能使用1,2,5,10个进程。如果我使用3,4 ..它将创建一个过程,而Q空,不会工作。

2 个答案:

答案 0 :(得分:0)

如果你想回收过程直到q为空,你应该尝试这样做:
代码1:

       def proccesframe():
           while(True):
               frame = queue.get()
               ##do something

你的过程将被阻止,直到队列中有东西为止 我不认为在菜单部分使用multiproccess很好,你应该在生产者身上使用它们。
如果你想在队列为空时终止procces,你可以这样做:
代码2:

       def proccesframe():
           while(!queue.empty()):
                 frame = queue.get()
                 ##do something
           terminate_procces()

更新

如果你想在消费者部分中使用多个过程,只需做一个简单的循环并添加code2,那么当你完成对队列的处理时,你就可以关闭你的过程。

答案 1 :(得分:0)

我不完全确定您要从解释中完成什么,但是您是否考虑过使用multiprocessing.Pool及其方法mapmap_async

from multiprocessing import Pool
from foo import bar # your function

if __name__ == "__main__":
    p = Pool(4) # your number of processes
    result = p.map_async(bar, [("arg #1", "arg #2"), ...])
    print result.get()

它在无序(!)迭代中收集函数的结果,你可以随意使用它。

<强>更新

我认为你不应该使用队列并且更直接:

from multiprocessing import Pool

def process_frame(fr): # PEP8 and see the difference in definition
    # magic
    return result # and result handling!

if __name__ == "__main__":
    p = Pool(4) # your number of processes
    results = p.map_async(process_frame, [fr_1, fr_2, ...])
    # Do not ever write or manipulate with files in parallel processes
    # if you are not 100% sure what you are doing!
    for result in results.get():
        commands_file.write(result)

更新2

from multiprocessing import Pool
import random
import time

def f(x):
    return x*x

def g(yr):
    with open("result.txt", "ab") as f:
        for y in yr:
            f.write("{}\n".format(y))

if __name__ == '__main__':
    pool = Pool(4)

    while True:
        # here you fetch new data and send it to process
        new_data = [random.randint(1, 50) for i in range(4)]
        pool.map_async(f, new_data, callback=g)

如何做到这一点的一些例子,我将算法更新为&#34;无限&#34;,它只能通过中断或从外部杀死命令来关闭。您也可以使用apply_async,但这会导致结果处理速度变慢(取决于处理速度)。

我也尝试在全局范围内使用长时间打开的result.txt,但每次都遇到死锁。