Python - 多进程代码成功地将结果返回到队列,但代码停止

时间:2013-08-31 17:51:04

标签: python multithreading multiprocessing

不知道你能帮帮忙吗?我是Python的新手,我正在尝试组合一段简单的代码来并行计算质数(跨越多个CPU内核)......我知道它很蹩脚,但它似乎是一段合理的代码来学习Python线程等。

我已成功设法使用Threads运行代码,但现在正在调查Process(es)。

下面的代码运行正常,直到我收集结果。我试过使用eclipse& amp; pdev调试器,并且发现我用于从outputQueue中删除项目的While循环似乎在3次迭代后仍然存在,因此代码实际上从未到达输出结果的阶段。

非常感谢任何想法/建议/帮助。

非常感谢

克雷格 ------代码

from multiprocessing import Process, Queue

# return true if number is prime, else false
def calcPrime(number):    
    divisor=2
    if number%2==0: 
        return False

    numberIsPrime=True
    while divisor*divisor <= number:   
        if number % divisor == 0:
            numberIsPrime = False
            break
        divisor = divisor + 1
    return numberIsPrime

# generate list of primes
def generatePrimes(minimum, maximum):
    return [num for num in range(minimum,maximum) if calcPrime(num)==True]

def workerThread(output, mn, mx):
    primelist=generatePrimes(mn,mx)
    output.put(primelist)

def main():
    outputQueue=Queue()

    t=[]
    t.append(Process(target=workerThread, args=(outputQueue, 1,25000)))
    t.append(Process(target=workerThread, args=(outputQueue, 25001, 50000)))
    t.append(Process(target=workerThread, args=(outputQueue, 50001, 75000)))
    t.append(Process(target=workerThread, args=(outputQueue, 75001, 100000)))

    #start all threads
    for idx in range(len(t)):
        t[idx].daemon=True
        t[idx].start()

    #wait for all process threads to complete
    for p in t:
        p.join()
    print("Processes finished")

    # gather all results
    l=[]
    while True:
        try:  
            l+=outputQueue.get()  # Code seems to stick here after about 3-4 iterations
        except:
            break

    #print out our lovely primes
    for idx in range(len(l)):
        print (str(l[idx]))    

# standard code        
if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:1)

此代码是一个无限循环:

l=[]
while True:
    try:  
        l+=outputQueue.get()  # Code seems to stick here after about 3-4 iterations
    except:
        break

get()的调用是阻止的,即它会等到您发送内容。 在您的情况下,当进程结束时,循环执行另一个永不返回的get()调用。

由于您知道进程数量,因此只需执行get() s:

l = sum((outputQueue.get() for _ in range(t)), [])

如果进程可以推送可变数量的结果,那么您可以在工作人员完成时发送一个sentinel值(例如None)。收集输出的进程可以计算它收到的哨兵数量,并最终停止查询队列。