Python多处理和参数传递需要帮助

时间:2014-02-19 03:57:57

标签: python-3.x multiprocessing argument-passing

您好我正在尝试在文档中运行多处理示例:http://docs.python.org/3.4/library/concurrent.futures.html,使用素数但差别很小的那个。

我希望能够调用具有多个参数的函数。我正在做的是将小块文本(在大约30k长的列表中)与更大的文本相匹配,并返回较大字符串中较小字符串开始的位置。

我可以这样连续地执行此操作:

matchList = []
for pattern in patterns:

    # Approximate pattern matching
    patternStartingPositions = processPattern(pattern, numMismatchesAllowed, transformedText, charToIndex, countMatrix, firstOccurrence, suffixArray)

    # Now add each starting position found onto our master list.
    for startPos in patternStartingPositions:
        matchList.append(startPos)

但我想这样做是为了加快速度:

matchList = []
with concurrent.futures.ProcessPoolExecutor() as executor:
    for pattern, res in zip(patterns, executor.map(processPattern(pattern, numMismatchesAllowed, transformedText, charToIndex, countMatrix, firstOccurrence, suffixArray), patterns)):
        print('%d is starts at: %s' % (pattern, res))

在这个阶段,我刚刚接到打印电话,因为我无法获得上述行,调用流程可以正常工作。

我想要做的和示例代码之间唯一真正的区别是我的函数需要7个参数,我不知道怎么做,花了半天时间。

上面的调用会产生此错误:

  

UnboundLocalError:局部变量'模式'在转让前引用。

这是有道理的。

但是如果我省略了第一个参数,即每个调用改变的参数,并将第一个参数省略到processPattern函数:

matchList = []
with concurrent.futures.ProcessPoolExecutor() as executor:
    for pattern, res in zip(patterns, executor.map(processPattern(numMismatchesAllowed, transformedText, charToIndex, countMatrix, firstOccurrence, suffixArray), patterns)):
        print('%d is starts at: %s' % (pattern, res))

然后我收到此错误:

  

TypeError:processPattern()缺少1个必需的位置参数:' suffixArray'。

我不知道如何在通话中获得pattern参数!

3 个答案:

答案 0 :(得分:3)

其他海报已经涵盖了可能的解决方案,但为了解释您的错误,您应该将函数和参数作为单独的对象传递给executor.map。以下是文档中的示例

with concurrent.futures.ProcessPoolExecutor() as executor:
    # is_prime is the function, PRIMES are the arguments
    for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): 
        print('%d is prime: %s' % (number, prime))

您的代码正在评估processPattern函数并将结果传递给executor.map

with concurrent.futures.ProcessPoolExecutor() as executor:
    for pattern, res in zip(patterns, executor.map(processPattern(numMis... # <- BAD
        print('%d is starts at: %s' % (pattern, res))

相反它应该是

with concurrent.futures.ProcessPoolExecutor() as executor:
    for pattern, res in zip(patterns, executor.map(processPattern, <stuff>)):
        print('%d is starts at: %s' % (pattern, res))

其中<stuff>是在每次后续调用中传递给processPattern的参数的可迭代。

或者,看到其他args保持不变,创建一个函数,只需要迭代一个参数并传入patterns作为迭代(如@ uhbif19所示)

编辑:

要扩展如何创建<stuff> iterable,您需要为函数所需的每个参数设置一个iterable(在本例中为processPattern)。您已将patterns作为参数1的可迭代项,如果其他参数不变,则itertools.repeat可能会有所帮助:

from itertools import repeat
args = (patterns, 
        repeat(numMismatchesAllowed, len(PATTERNS)),
        repeat(transformedText, len(PATTERNS)),
        repeat(charToIndex, len(PATTERNS)),
        <etc...>
        )

然后

for pattern, res in zip(PATTERNS, executor.map(process, *args)):

我为了理解而加入了这个,但是你可以看出这是多么的混乱。其他答案提供了更好的解决方案。

编辑2:

这是一个更好地说明提交与地图

的使用的示例
import concurrent.futures

def process(a, b):
    return a.upper() + b

with concurrent.futures.ProcessPoolExecutor() as executor:
    for c, fut in [(c, executor.submit(process, c, 'b')) for c in 'testing']:
        print(c, fut.result())

with concurrent.futures.ProcessPoolExecutor() as executor:
    for c, res in zip('testing', executor.map(process, 'testing', 'bbbbbbb')):
        print(c, str(res))

答案 1 :(得分:2)

要将数据设置为正确的形状,只需使用生成器表达式(根本不需要zip)并使用submit而不是map

(pattern, executor.submit(processPattern, pattern, ...) for pattern in patterns)

要确保所有内容都在池上执行(而不是立即执行),请不要像在示例中那样调用processPatterns函数,而是将其作为第一个参数传递给{{1} }。您的代码的固定版本将是:

.submit

答案 2 :(得分:1)

用于 -loop的Python 具有功能行为,并且无法更改迭代的值。

with concurrent.futures.ProcessPoolExecutor() as executor:

    def work(pattern):
        return processPattern(pattern, numMismatchesAllowed, transformedText, charToIndex, countMatrix, firstOccurrence, suffixArray)

    results = executor.map(work, patterns)

    for pattern, res in zip(patterns, results):
        print('%d is starts at: %s' % (pattern, res)) 

事实上,对于不使用 continue break 指令的循环,就像地图功能一样。那就是:

for i in something:
    work(i)

相当于

map(work, something)