多处理池挂起,无法脱离应用程序

2024-04-29 14:07:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我确信这是一个新手犯的错误,但我不知道我在多处理方面做错了什么。我有这个代码(它只是坐在那里什么也不做)

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上发送要完成的每个项目,但是当我将工作命令包装成一个函数并发送此代码时,它不会做任何事情(当我在没有上述代码的情况下调用函数本身时,它可以正常工作)。所以我认为我使用多处理是错误的(虽然我从网站上拿了一些例子),有什么建议吗?

更新:我注意到,当它被control-c冻结时,我甚至都无法从中脱离出来,这总是可以从我的程序中摆脱出来。我查看了python2.5 multiprocessing Pool并尝试按照建议在if语句中添加导入,但没有成功

Update2:很抱歉,我刚刚意识到,由于下面的回答,该命令可以工作,但似乎没有终止程序或让我强制退出。


Tags: 代码namein命令程序列表forif
3条回答

你的代码似乎对我有用:

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!

多处理不是线程。

你可能在做这样的事

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。你不能做的是改变你的程序状态并期望它工作。

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

在linux上,使用fork(),在启动子进程时,它会复制内存中的所有内容。但是,像套接字、打开的文件和数据库连接这样的东西不能正常工作,除非专门为此而设计。

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

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

说实话,你这样做不会有任何进展。事实上,我希望这会慢一些。看数据库真的很慢。您的进程将花费大部分时间等待数据库。现在您只有多个进程在等待数据库,这并不能改善情况。

但是数据库是用来存储东西的。只要您正在进行处理,您就应该在进入数据库之前在代码中进行处理。基本上,您使用的是数据库a s a set,而使用python set,您的代码会好得多。如果你真的需要把这些东西放进数据库,在程序结束时做。

相关问题 更多 >