我试图理解Python的多处理模块是如何工作的。为此,我制作了一个非常简单的代码版本,并尝试使其并行工作。根据我的阅读,使用pool
比使用mp.Process
更适合我的程序。
以下是我提出的建议:
import time, os
import multiprocessing as mp
class Foo:
def __init__(self, ID):
self.ID = ID
def showID(self):
for k in range(0,4):
print('Foo #', self.ID, '\tID:', os.getpid(), '\tParent ID:', os.getppid())
time.sleep(0.2)
# MAIN
if __name__ == '__main__':
print('parent process:', os.getppid())
print('process id:', os.getpid())
print(' ')
foos = [Foo(2), Foo(3)]
pool = mp.Pool(processes=2)
# Code below doesn't work
pool.apply_async(foos[0].showID, ())
pool.apply_async(foos[1].showID, ())
列表foos
最终将包含10到20个对象。方法Foo.showID
最终也会返回一些东西。我的目标是在它们运行时发送尽可能多的任务(foos
成员),以便将它们分派到pool
个进程之一。
如果我运行上面的代码,没有任何反应,即。仅显示开头的parent process
和process id
。如果我将最后两行替换为:
pool.apply_async(foos[0].showID())
pool.apply_async(foos[1].showID())
它们都是在主进程中一个接一个地执行的:
parent process: 3380
process id: 6556
Foo # 2 ID: 6556 Parent ID: 3380
Foo # 2 ID: 6556 Parent ID: 3380
Foo # 2 ID: 6556 Parent ID: 3380
Foo # 2 ID: 6556 Parent ID: 3380
Foo # 3 ID: 6556 Parent ID: 3380
Foo # 3 ID: 6556 Parent ID: 3380
Foo # 3 ID: 6556 Parent ID: 3380
Foo # 3 ID: 6556 Parent ID: 3380
最后,如果我用这样的东西替换它们:
pool.apply_async(foos[0].showID, ())
pool.apply_async(foos[1].showID())
我得到了预期的行为(我认为):
parent process: 3380
process id: 4772
Foo # 3 ID: 4772 Parent ID: 3380
Foo # 2 ID: 6364 Parent ID: 4772
Foo # 3 ID: 4772 Parent ID: 3380
Foo # 2 ID: 6364 Parent ID: 4772
Foo # 3 ID: 4772 Parent ID: 3380
Foo # 2 ID: 6364 Parent ID: 4772
Foo # 3 ID: 4772 Parent ID: 3380
Foo # 2 ID: 6364 Parent ID: 4772
这里发生了什么?如果我尝试使用未在Foo
类中定义的函数,我注意到了相同的行为。
答案 0 :(得分:1)
apply_async收到一个功能
当您使用没有括号的foos[0].showID
时,您正在传递函数,而不是调用它,但是在执行时
pool.apply_async(foos[0].showID())
您首先评估foos[0].showID()
,然后将其返回值作为参数传递给apply_async
。最终进行评估的是apply_async
的调用者和同步处理。
这相当于:
foos[0].showID()
pool.apply_async()
foos[1].showID()
pool.apply_async()
您的第一次尝试失败,因为您没有等待异步调用执行。打电话后。
pool.apply_async(foos[0].showID, ())
pool.apply_async(foos[1].showID, ())
您的程序退出,因此您不必等待输出。
最后
pool.apply_async(foos[0].showID, ())
pool.apply_async(foos[1].showID())
相当于:
pool.apply_async(foos[0].showID, ())
foos[1].showID()
进行一次异步通话和一次同步通话,这样就可以了。
答案 1 :(得分:1)
原始代码的问题在于您没有等待子进程执行工作。您安排了工作项并退出导致池杀死了工作人员。在计划作业时保留返回的结果对象并等待它们完成。
import time, os
import multiprocessing as mp
class Foo:
def __init__(self, ID):
self.ID = ID
def showID(self):
for k in range(0,4):
print('Foo #', self.ID, '\tID:', os.getpid(), '\tParent ID:', os.getppid())
time.sleep(0.2)
# MAIN
if __name__ == '__main__':
print('parent process:', os.getppid())
print('process id:', os.getpid())
print(' ')
foos = [Foo(2), Foo(3)]
pool = mp.Pool(processes=2)
results = []
results.append(pool.apply_async(foos[0].showID, ()))
results.append(pool.apply_async(foos[1].showID, ()))
for result in results:
result.wait()