Python多处理> = 125列表永远不会完成

时间:2013-09-28 20:50:17

标签: python multiprocessing

我正在尝试为我自己的目的实现这个多处理tutorial。起初我认为它不能很好地扩展,但是当我做了一个可重复的例子时,我发现如果项目列表超过124,它似乎永远不会返回答案。在x = 124,它在.4秒内运行,但当我将其设置为x = 125时,它永远不会完成。我在Windows 7上运行Python 2.7。

from multiprocessing import Lock, Process, Queue, current_process
import time

class Testclass(object):
    def __init__(self, x):
        self.x = x

def toyfunction(testclass):
    testclass.product = testclass.x * testclass.x
    return testclass


def worker(work_queue, done_queue):
    try:
        for testclass in iter(work_queue.get, 'STOP'):
            print(testclass.counter)
            newtestclass = toyfunction(testclass)
            done_queue.put(newtestclass)

    except:
        print('error')

    return True

def main(x):

    counter = 1

    database = []
    while counter <= x:
        database.append(Testclass(10))
        counter += 1
        print(counter)



    workers = 8
    work_queue = Queue()
    done_queue = Queue()
    processes = []

    start = time.clock()
    counter = 1

    for testclass in database:
        testclass.counter = counter
        work_queue.put(testclass)
        counter += 1
        print(counter)


    print('items loaded')
    for w in range(workers):
        p = Process(target=worker, args=(work_queue, done_queue))
        p.start()
        processes.append(p)
        work_queue.put('STOP')

    for p in processes:
        p.join()

    done_queue.put('STOP')

    newdatabase = []
    for testclass in iter(done_queue.get, 'STOP'):
        newdatabase.append(testclass)

    print(time.clock()-start)
    print("Done")
    return(newdatabase)

if __name__ == '__main__':
    database = main(124)
    database2 = main(125)

1 个答案:

答案 0 :(得分:6)

OK!来自the docs

  

警告如上所述,如果子进程已将项目放在队列中(并且没有   使用JoinableQueue.cancel_join_thread),然后该进程将不会终止直到所有   已缓冲的项目已刷新到管道。   这意味着如果您尝试加入该过程,除非您确定,否则可能会遇到死锁   已经消耗了所有已放入队列的项目。同样,如果   子进程是非守护进程,然后父进程在尝试时可能会在退出时挂起   加入所有非守护儿童。请注意,使用管理器创建的队列可以   没有这个问题。请参阅编程指南。

正如我之前在评论中提到的那样,代码尝试.join()进程之前排除done_queue队列 - 并且在以一种时髦的方式更改代码之后确保在done_queue之前.join()被耗尽,代码在一百万件项目中运行良好。

所以这是导航错误的一个例子,虽然相当模糊。至于为什么行为取决于传递给main(x)的数字,它是不可预测的:它取决于内部如何进行缓冲。这样的乐趣; - )