我可以将 map / imap / imap_unordered 与不带参数的函数一起使用吗?
Posted
技术标签:
【中文标题】我可以将 map / imap / imap_unordered 与不带参数的函数一起使用吗?【英文标题】:Can I use map / imap / imap_unordered with functions with no arguments? 【发布时间】:2015-02-25 16:42:41 【问题描述】:有时我需要对不带参数的函数使用多处理。我希望我能做这样的事情:
from multiprocessing import Pool
def f(): # no argument
return 1
# TypeError: f() takes no arguments (1 given)
print Pool(2).map(f, range(10))
我可以使用Process(target=f, args=())
,但我更喜欢map
/ imap
/ imap_unordered
的语法。有没有办法做到这一点?
【问题讨论】:
您愿意重新定义f
以接受一个论点并忽略它吗?
@inspectorG4dget:不,我宁愿避免
我感觉这是XY problem。那么,让我们退后一步:您实际上想要做什么,您尝试使用此功能是为了什么?
map
的语义意味着您将一个函数映射到一个输入序列,这就是您所得到的。无论您决定忽略该参数,还是创建一个由您决定的包装函数。
@inspectorG4dget:一个例子是对数据库或 API 进行压力测试。我需要生成 N 个相同的进程来重复发送请求。
【参考方案1】:
map
函数的第一个参数应该是一个函数并且它应该接受一个参数。这是强制性的,因为作为第二个参数传递的可迭代对象将被迭代,并且值将在每次迭代中一个一个地传递给函数。
所以,最好的办法是重新定义f
以接受一个参数并忽略它,或者编写一个带有一个参数的包装函数,忽略该参数并返回f
的返回值,像这样
from multiprocessing import Pool
def f(): # no argument
return 1
def throw_away_function(_):
return f()
print(Pool(2).map(throw_away_function, range(10)))
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
您不能将 lamdba
函数与池一起使用,因为它们不可提取。
【讨论】:
它不必是只接受一个参数的函数。如果要传递更多参数,可以使用 partial。【参考方案2】:使用Pool.apply_async
有什么问题吗?
with multiprocessing.Pool() as pool:
future_results = [pool.apply_async(f) for i in range(n)]
results = [f.get() for f in future_results]
【讨论】:
这会引发错误 (Python 2.7): with multiprocessing.Pool() as pool: AttributeError: exit【参考方案3】:您可以像这样使用pool.starmap()
而不是.map()
:
from multiprocessing import Pool
def f(): # no argument
return 1
print Pool(2).starmap(f, [() for _ in range(10)])
starmap
会将给定迭代的所有元素作为参数传递给f
。在你的情况下,迭代应该是空的。
【讨论】:
以上是关于我可以将 map / imap / imap_unordered 与不带参数的函数一起使用吗?的主要内容,如果未能解决你的问题,请参考以下文章
multiprocessing.Pool:map_async 和 imap 有啥区别?
如何使用 Python imaplib 为 IMAP (Gmail) 启用推送通知?