具有Map的Python多处理:运行整个脚本,而不仅仅是子功能

时间:2017-09-14 15:44:40

标签: python dictionary multiprocessing pool

我试图使用Python的多处理地图功能。我把地图调用放在一个子函数中,因为我需要循环一个更大的数据集来分割它并在较小的块上调用map。

我的问题是time.sleep(5)行被多次调用并且'测试!'正在打印5次(在开始时看起来等于一次,然后循环次数为2 * 2 *进程数),即使它处于比多处理调用更高的级别。但是,同时,CSV输出是我所期望的,因此runParallel()按预期运行并被称为预期的次数。

from multiprocessing import Pool
import numpy as np
import os,csv,copy,time
from AuxFuncs import *

def master():    
    time.sleep(5)
    print('Test!')
    for mult in [1,10]:
        runParallel(mult)

def runParallel(mult):
    randIntInputs = list()
    for i in range(5): randIntInputs.append((np.random.randint(10)*mult,mult))
    if __name__=='__main__':
        p = Pool(processes=2)
        results = p.map(testFunc,randIntInputs)
        p.close()
        p.join()
        valsToSave = [list(result[0]) for result in results]
        write2dListToCSV(valsToSave,'output' + str(mult) + '.csv')

def testFunc(inputs):
    return np.random.randint(1,10,5) * inputs[0],inputs[1]

master()

输出是:

Test!
Test!
Test!
Test!
Test!

我认为问题可能是我将Pool调用放在一个函数中,但即使我将它移出函数,我也有同样的问题("测试!"打印3次通过以下代码。)

from multiprocessing import Pool
import numpy as np
import os,csv,copy,time
from AuxFuncs import *

def testFunc(inputs):
    return np.random.randint(1,10,5) * inputs[0],inputs[1]

print('Test!')
mult,randIntInputs = 5,list()
for i in range(5): randIntInputs.append((np.random.randint(10)*mult,mult))
if __name__=='__main__':
    p = Pool(processes=2)
    results = p.map(testFunc,randIntInputs)
    p.close()
    p.join()
    valsToSave = [list(result[0]) for result in results]
    write2dListToCSV(valsToSave,'output' + str(mult) + '.csv')

编辑: 谢谢您的帮助。看起来像这样:

来自多处理导入池 导入numpy为np import os,csv,copy,time 来自AuxFuncs import *

def master():    
    if __name__=='__main__':
        time.sleep(5)
        print('Test!')
        for mult in [1,10]:
            runParallel(mult)

def runParallel(mult):
    randIntInputs = list()
    for i in range(5): randIntInputs.append((np.random.randint(10)*mult,mult))
    # if __name__=='__main__':
    p = Pool(processes=2)
    results = p.map(testFunc,randIntInputs)
    p.close()
    p.join()
    valsToSave = [list(result[0]) for result in results]
    write2dListToCSV(valsToSave,'output' + str(mult) + '.csv')

def testFunc(inputs):
    return np.random.randint(1,10,5) * inputs[0],inputs[1]

master()

1 个答案:

答案 0 :(得分:0)

这里可能发生的是每个进程都在尝试导入您调用的函数。当发生这种情况时,它会运行在定义之外调用的任何函数,或者不会被if屏蔽,包括您对master的调用。将if __name__ ...放在定义中不允许您使用它来屏蔽其他操作。我认为你的目标看起来更像是这样:

def master():
    time.sleep(5)
    print('Test!')
    for mult in range(1, 11):
        runParallel(mult)

def runParallel(mult):
    randIntInputs = list()
    for i in range(5): randIntInputs.append((np.random.randint(10)*mult,mult))
    with Pool(processes=2) as p:
        results = p.map(testFunc,randIntInputs)
    valsToSave = [list(result[0]) for result in results]
    write2dListToCSV(valsToSave,'output' + str(mult) + '.csv')

def testFunc(inputs):
    return np.random.randint(1,10,5) * inputs[0],inputs[1]

if __name__ == '__main__':
    master()

这与您上一次更新之间的区别在于,在您的更新主数据库仍然为每个进程调用时,它只是没有做任何事情,因为if语句没有评估True ;但在此代码中,它只调用master一次,并在if语句之后每次都被阻止。差异并不大,但这个版本更加实用。

顺便说一句,我冒昧地使用with语句将您的池放在上下文管理器中。一旦上下文退出,这将自动关闭Pool。我还删除了.join()因为Pool().map()函数已经暂停主线程直到它返回。最后,我将您在master中创建的临时列表更改为对range的调用。 range用于在输入的两个之间创建一系列数字,包括左侧但不包括右侧。使用单个参数,它使用0作为起始点并上升到指定的数字; range(10) => 0 1 2 3 4 5 6 7 8 9