您好我正在尝试在文档中运行多处理示例: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
参数!
答案 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)