我试图了解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 processprocess 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类内部定义的函数,我会注意到相同的行为。

最佳答案

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()


进行一个异步调用和一个同步调用,因此可以正常工作。

关于python - 了解简单的多处理脚本,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36117544/

10-11 07:45