我可以将 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) 启用推送通知?

多处理计算中map()模块和imap()之间的差异

如何使用 purrr(管道、地图、imaps)将 df 或 tibble 中的两列组合绘制为 R 中的散点图

如何匹配引号,自动括号括号括号和括号中的括号?

为啥我在通过 IMAP 连接到 Gmail 时收到“需要 Web 登录”消息?