【问题标题】:Can I use map / imap / imap_unordered with functions with no arguments?我可以将 map / imap / imap_unordered 与不带参数的函数一起使用吗?
【发布时间】: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 个相同的进程来重复发送请求。

标签: python python-multiprocessing


【解决方案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。在你的情况下,迭代应该是空的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-13
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多