我正在为几组迭代运行一个函数,一旦所有进程都完成就会返回所有结果的列表。
def fct(variable1, variable2):
# do an operation that does not necessarily take the same amount of
# time for different input variables and yields result1 and result2
return result1, result2
variables1 = [1,2,3,4]
variables2 = [7,8,9,0]
with ThreadPoolExecutor(max_workers = 8) as executor:
future = executor.map(fct,variables1,variables2)
print '[%s]' % ', '.join(map(str, future))
>>> [ (12,3) , (13,4) , (14,5) , (15,6) ]
如何打印中间结果,例如对于变量1 = 1,变量2 = 7,只要计算出它们的结果?
答案 0 :(得分:4)
如果您希望在完成的情况下使用结果而不保留原始可迭代的顺序,则可以使用executor.submit
和concurrent.futures.as_completed
:
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import random
def fct(variable1, variable2):
time.sleep(random.randint(1,5))
return variable1+1, variable2+1
variables1 = [1,2,3,4]
variables2 = [7,8,9,0]
with ThreadPoolExecutor(max_workers = 8) as executor:
for out in as_completed([executor.submit(fct,*vars)
for vars in zip(variables1, variables2)]):
print(out.result())
输出(尽管由于random.randint
而在任何给定的运行中都可以执行任何订单):
(4, 10)
(5, 1)
(2, 8)
(3, 9)
只要as_completed
标记为已完成, Future
将从其输入列表中产生Future
,无论它实际落在输入列表中的哪个位置。这样,如果第二个项目在2秒后完成,但第一个项目需要15秒,您将在两秒钟后看到第二个项目的结果,而不是需要等待十五个。这可能是也可能不是理想的行为,具体取决于您的具体用例。
修改强>
请注意,您仍然可以通过这种方式获得原始订单的输出。您只需要将列表保存到as_completed
:
with ThreadPoolExecutor(max_workers = 8) as executor:
jobs = [executor.submit(fct, *vars)
for vars in zip(variables1, variables2)]
for out in as_completed(jobs):
print(out.result())
results = [r.result() for r in jobs]
print(results)
输出:
(5, 1)
(2, 8)
(3, 9)
(4, 10)
[(2, 8), (3, 9), (4, 10), (5, 1)]
答案 1 :(得分:3)
map
已经这样做,但是join
需要使用整个iterable来创建连接的字符串。将其更改为for
循环将允许您以递增方式打印它:
for i in executor.map(fct, v1, v2):
print(str(i))
保持与join
代码相同的输出是一项更多的工作,但无论如何都可行:
first = True
print("[ ", end="")
for i in executor.map(fct, v1, v2):
if first:
first = False
else:
print(" , ", end="")
print(str(i), end="")
print("]", end="")