多处理池挂起,无法突破应用程序

时间:2012-02-18 23:27:19

标签: python multiprocessing

我确定这是一个新手的错误,但我无法弄清楚我在多处理方面做错了什么。我有这个代码(只是坐着,什么都不做)

if __name__ == '__main__':
    pool = Pool(processes=4)  
    for i, x in enumerate(data): 
        pool.apply_async(new_awesome_function, (i, x))
    pool.close()
    pool.join()

数据是一个列表([1,2,3,4,5]),我试图把列表发送每个项目来完成多个cpu但是当我将我的工作命令包装成一个函数并发送这段代码它没有做任何事情(当我没有上面的代码调用函数本身它工作正常)。所以我认为我使用多处理错误(虽然我从网站上拿了例子),有什么建议吗?

更新:我注意到,当它冻结控制时,我甚至无法突破它。这总是能够摆脱我的错误程序。我查看python2.5 multiprocessing Pool并试图按照建议添加导入我的if语句但没有运气

更新2:对不起,刚刚意识到下面的答案,该命令有效,但它似乎没有终止程序或让我强制退出。

3 个答案:

答案 0 :(得分:3)

多处理不是线程化。

你可能正在做这样的事情

data = {}

def new_awesome_function(a, b):
    data[a] = b

运行脚本后,数据未更改。这是因为多处理使用程序的副本。您的功能正在运行,但它们以您的程序副本运行,因此对您的原始程序没有影响。

为了使用多处理,您需要明确地从一个进程通信到另一个进程。使用线程,一切都是共享的,但是使用多处理,除非您明确地共享它,否则不会共享任何内容。

最简单的方法是使用返回值:

def new_awesome_function(a, b):
    return a + b

result = pool.apply_async(new_awesome_function, (1, 2))
# later...
value = result.get()

有关队列,管道和管理器等其他方法,请参阅python文档:http://docs.python.org/library/multiprocessing.html。你不能做的是改变你的程序状态并希望它能够工作。

答案 1 :(得分:2)

您的代码似乎对我有用:

from multiprocessing import Pool
import time

def new_awesome_function(a,b):
    print(a,b, 'start')
    time.sleep(1)
    print(a,b, 'end')

if __name__ == '__main__':
    data = [1,2,3,4,5]
    pool = Pool(processes=4)
    for i, x in enumerate(data): 
        pool.apply_async(new_awesome_function, (i, x))
    pool.close()
    pool.join()

给了我:

0 1 start
1 2 start
2 3 start
3 4 start
1 2 end
0 1 end
4 5 start
2 3 end
3 4 end
4 5 end

是什么让你认为它不起作用?


编辑:尝试运行此操作并查看输出:

from multiprocessing import Pool
import time

def new_awesome_function(a,b):
    print(a,b, 'start')
    time.sleep(1)
    print(a,b, 'end')
    return a + b

if __name__ == '__main__':
    data = [1,2,3,4,5]
    pool = Pool(processes=4)
    results = []
        for i, x in enumerate(data): 
        r = pool.apply_async(new_awesome_function, (i, x))
        results.append((i,r))
    pool.close()
    already = []
    while len(already) < len(data):
        for i,r in results:
            if r.ready() and i not in already:
                already.append(i)
                print(i, 'is ready!')
    pool.join()

我的是:

0 1 start
1 2 start
2 3 start
3 4 start
0 1 end
4 5 start
1 2 end
2 3 end
0 is ready!
3 4 end
1 is ready!
2 is ready!
3 is ready!
4 5 end
4 is ready!

答案 2 :(得分:2)

我不知道你正在使用什么数据库,但你可能无法在你的进程之间共享数据库连接。

在linux上,使用fork(),它在启动子进程时复制内存中的所有内容。但是,除非专门设计,否则诸如套接字,打开文件和数据库连接之类的东西将无法正常工作。

在窗口上,fork()不可用,因此它将重新运行您的脚本。在你的情况下,这将是非常糟糕的,因为它会再次放弃一切。您可以通过放入if __name__ == '__main__':位来防止这种情况。

您应该能够在my_awesome_function中重新打开数据库连接,从而能够与数据库进行成功的交互。

说实话,你不会在这方面获得任何速度。事实上,我预计这会变慢。看数据库真的很慢。您的进程将花费大部分时间等待数据库。现在你只有多个进程在等待数据库,这实际上不会改善这种情况。

但数据库用于存储东西。只要您正在进行处理,您应该在访问数据库之前在代码中执行此操作。你基本上使用的是数据库集合,使用python集你的代码会更好。如果你真的需要把这些东西放在数据库中,那就在程序结束时这样做。