concurrent.futures.Executor.map
采用可变数量的迭代,从中调用给定的函数。 如果我的生成器生成通常已解压缩的元组,我该如何调用它?
以下方法不起作用,因为每个生成的元组都作为map的不同参数给出:
args = ((a, b) for (a, b) in c)
for result in executor.map(f, *args):
pass
如果没有生成器,映射的所需参数可能如下所示:
executor.map(
f,
(i[0] for i in args),
(i[1] for i in args),
...,
(i[N] for i in args),
)
答案 0 :(得分:29)
c
from itertools import repeat
for result in executor.map(f, repeat(a), c):
pass
c
项,并解压c
from itertools import izip
for result in executor.map(f, *izip(*c)):
pass
c
项,无法解包c
f
以获取单个参数并在函数中解压缩参数。如果c
中的每个项目都有可变数量的成员,或者您只是呼叫f
几次:
executor.map(lambda args, f=f: f(*args), c)
它定义了一个新功能,可以从c
解包每个项目并调用f
。在f
中使用lambda
的默认参数会使f
内的lambda
本地化,从而减少查找时间。
如果您有一定数量的参数,并且需要多次调用f
:
from collections import deque
def itemtee(iterable, n=2):
def gen(it = iter(iterable), items = deque(), next = next):
popleft = items.popleft
extend = items.extend
while True:
if not items:
extend(next(it))
yield popleft()
return [gen()] * n
executor.map(f, *itemtee(c, n))
n
是f
的参数数量。这改编自itertools.tee
。
答案 1 :(得分:23)
您需要移除*
电话上的map
:
args = ((a, b) for b in c)
for result in executor.map(f, args):
pass
这将调用f
,len(args)
次,其中f
应接受一个参数。
如果您希望f
接受两个参数,可以使用lambda调用,如:
args = ((a, b) for b in c)
for result in executor.map(lambda p: f(*p), args): # (*p) does the unpacking part
pass
答案 2 :(得分:3)
您可以使用currying通过Python中的partial方法创建新函数
from concurrent.futures import ThreadPoolExecutor
from functools import partial
def some_func(param1, param2):
# some code
# currying some_func with 'a' argument is repeated
func = partial(some_func, a)
with ThreadPoolExecutor() as executor:
executor.map(func, list_of_args):
...
如果您需要传递多个相同的参数,则可以将它们传递给partial方法
func = partial(some_func, a, b, c)
答案 3 :(得分:3)
以下代码片段展示了如何使用 ThreadPoolExecutor 向函数发送多个参数:
import concurrent.futures
def hello(first_name: str, last_name: str) -> None:
"""Prints a friendly hello with first name and last name"""
print('Hello %s %s!' % (first_name, last_name))
def main() -> None:
"""Examples showing how to use ThreadPoolExecutor and executer.map
sending multiple arguments to a function"""
# Example 1: Sending multiple arguments using tuples
# Define tuples with sequential arguments to be passed to hello()
args_names = (
('Bruce', 'Wayne'),
('Clark', 'Kent'),
('Diana', 'Prince'),
('Barry', 'Allen'),
)
with concurrent.futures.ThreadPoolExecutor() as executor:
# Using lambda, unpacks the tuple (*f) into hello(*args)
executor.map(lambda f: hello(*f), args_names)
print()
# Example 2: Sending multiple arguments using dict with named keys
# Define dicts with arguments as key names to be passed to hello()
kwargs_names = (
{'first_name': 'Bruce', 'last_name': 'Wayne'},
{'first_name': 'Clark', 'last_name': 'Kent'},
{'first_name': 'Diana', 'last_name': 'Prince'},
{'first_name': 'Barry', 'last_name': 'Allen'},
)
with concurrent.futures.ThreadPoolExecutor() as executor:
# Using lambda, unpacks the dict (**f) into hello(**kwargs)
executor.map(lambda f: hello(**f), kwargs_names)
if __name__ == '__main__':
main()
答案 4 :(得分:0)
类似于map(func,* iterables),除了:
立即迭代而不是懒惰地收集可迭代对象;
func是异步执行的,可能会对func进行了多次调用 同时进行。
尝试在python 3下运行以下代码段,您将很清楚:
from concurrent.futures import ProcessPoolExecutor
def f(a, b):
print(a+b)
with ProcessPoolExecutor() as pool:
pool.map(f, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (0, 1, 2))
# 0, 2, 4
array = [(i, i) for i in range(3)]
with ProcessPoolExecutor() as pool:
pool.map(f, *zip(*array))
# 0, 2, 4
答案 5 :(得分:0)
我在这里看到了很多答案,但是没有一个比使用lambda表达式更直接:
foo(x,y): 通过
想用相同的值(即xVal和yVal)调用上述方法10次吗? 将并发.futures.ThreadPoolExecutor()作为执行者:
for _ in executor.map( lambda _: foo(xVal, yVal), range(0, 10)):
pass
答案 6 :(得分:0)
因此,假设您有一个带有 3个参数的函数,并且所有3个参数都是 dynamic ,并且每次调用时都在不断变化。例如:
def multiply(a,b,c):
print(a * b * c)
要使用线程多次调用此函数,我首先要创建一个元组列表,其中每个元组都是a,b,c的一个版本:
arguments = [(1,2,3), (4,5,6), (7,8,9), ....]
我们知道concurrent.futures
的{{1}}函数将第一个参数作为 target函数,将第二个参数作为参数列表对于将要执行的功能的每个版本。因此,您可以这样拨打电话:
map
但这会给您错误,该函数期望for _ in executor.map(multiply, arguments) # Error
。为了解决这个问题,我们创建了一个辅助函数:
3 arguments but got only 1
现在,我们可以使用executor调用此函数,如下所示:
def helper(numbers):
multiply(numbers[0], numbers[1], numbers[2])
那应该给您想要的结果。
答案 7 :(得分:0)
假设您在下面显示的数据框中有这样的数据,并且您想将第一两列传递给一个函数,该函数将读取图像并预测特征,然后计算差异并返回差异值。
注意:您可以根据您的要求设置任何场景,并且可以分别定义函数。
下面的代码片段将这两列作为参数并传递给线程池机制(也显示进度条)
''' function that will give the difference of two numpy feature matrix'''
def getDifference(image_1_loc, image_2_loc, esp=1e-7):
arr1 = ''' read 1st image and extract feature '''
arr2 = ''' read 2nd image and extract feature '''
diff = arr1.ravel() - arr2.ravel() + esp
return diff
'''Using ThreadPoolExecutor from concurrent.futures with multiple argument'''
with ThreadPoolExecutor() as executor:
result = np.array(
list(tqdm(
executor.map(lambda x : function(*x), [(i,j) for i,j in df[['image_1','image_2']].values]),
total=len(df)
)
)
)